diff --git a/adev-ja/src/content/guide/forms/dynamic-forms.en.md b/adev-ja/src/content/guide/forms/dynamic-forms.en.md new file mode 100644 index 0000000000..60d0de0af3 --- /dev/null +++ b/adev-ja/src/content/guide/forms/dynamic-forms.en.md @@ -0,0 +1,143 @@ +# Building dynamic forms + +Many forms, such as questionnaires, can be very similar to one another in format and intent. +To make it faster and easier to generate different versions of such a form, you can create a _dynamic form template_ based on metadata that describes the business object model. +Then, use the template to generate new forms automatically, according to changes in the data model. + +The technique is particularly useful when you have a type of form whose content must change frequently to meet rapidly changing business and regulatory requirements. +A typical use-case is a questionnaire. +You might need to get input from users in different contexts. +The format and style of the forms a user sees should remain constant, while the actual questions you need to ask vary with the context. + +In this tutorial you will build a dynamic form that presents a basic questionnaire. +You build an online application for heroes seeking employment. +The agency is constantly tinkering with the application process, but by using the dynamic form +you can create the new forms on the fly without changing the application code. + +The tutorial walks you through the following steps. + +1. Enable reactive forms for a project. +1. Establish a data model to represent form controls. +1. Populate the model with sample data. +1. Develop a component to create form controls dynamically. + +The form you create uses input validation and styling to improve the user experience. +It has a Submit button that is only enabled when all user input is valid, and flags invalid input with color coding and error messages. + +The basic version can evolve to support a richer variety of questions, more graceful rendering, and superior user experience. + +## Enable reactive forms for your project + +Dynamic forms are based on reactive forms. + +To give the application access reactive forms directives, import `ReactiveFormsModule` from the `@angular/forms` library into the necessary components. + +The following code from the example shows the setup in the root module. + + + + + + +## Create a form object model + +A dynamic form requires an object model that can describe all scenarios needed by the form functionality. +The example hero-application form is a set of questions — that is, each control in the form must ask a question and accept an answer. + +The data model for this type of form must represent a question. +The example includes the `DynamicFormQuestionComponent`, which defines a question as the fundamental object in the model. + +The following `QuestionBase` is a base class for a set of controls that can represent the question and its answer in the form. + + + +### Define control classes + +From this base, the example derives two new classes, `TextboxQuestion` and `DropdownQuestion`, that represent different control types. +When you create the form template in the next step, you instantiate these specific question types in order to render the appropriate controls dynamically. + +The `TextboxQuestion` control type is represented in a form template using an `` element. It presents a question and lets users enter input. The `type` attribute of the element is defined based on the `type` field specified in the `options` argument (for example `text`, `email`, `url`). + + + +The `DropdownQuestion` control type presents a list of choices in a select box. + + + +### Compose form groups + +A dynamic form uses a service to create grouped sets of input controls, based on the form model. +The following `QuestionControlService` collects a set of `FormGroup` instances that consume the metadata from the question model. +You can specify default values and validation rules. + + + +## Compose dynamic form contents + +The dynamic form itself is represented by a container component, which you add in a later step. +Each question is represented in the form component's template by an `` tag, which matches an instance of `DynamicFormQuestionComponent`. + +The `DynamicFormQuestionComponent` is responsible for rendering the details of an individual question based on values in the data-bound question object. +The form relies on a [`[formGroup]` directive](api/forms/FormGroupDirective "API reference") to connect the template HTML to the underlying control objects. +The `DynamicFormQuestionComponent` creates form groups and populates them with controls defined in the question model, specifying display and validation rules. + + + + + + +The goal of the `DynamicFormQuestionComponent` is to present question types defined in your model. +You only have two types of questions at this point but you can imagine many more. +The `ngSwitch` statement in the template determines which type of question to display. +The switch uses directives with the [`formControlName`](api/forms/FormControlName "FormControlName directive API reference") and [`formGroup`](api/forms/FormGroupDirective "FormGroupDirective API reference") selectors. +Both directives are defined in `ReactiveFormsModule`. + +### Supply data + +Another service is needed to supply a specific set of questions from which to build an individual form. +For this exercise you create the `QuestionService` to supply this array of questions from the hard-coded sample data. +In a real-world app, the service might fetch data from a backend system. +The key point, however, is that you control the hero job-application questions entirely through the objects returned from `QuestionService`. +To maintain the questionnaire as requirements change, you only need to add, update, and remove objects from the `questions` array. + +The `QuestionService` supplies a set of questions in the form of an array bound to `@Input()` questions. + + + +## Create a dynamic form template + +The `DynamicFormComponent` component is the entry point and the main container for the form, which is represented using the `` in a template. + +The `DynamicFormComponent` component presents a list of questions by binding each one to an `` element that matches the `DynamicFormQuestionComponent`. + + + + + + +### Display the form + +To display an instance of the dynamic form, the `AppComponent` shell template passes the `questions` array returned by the `QuestionService` to the form container component, ``. + + + +This separation of model and data lets you repurpose the components for any type of survey, as long as it's compatible with the _question_ object model. + +### Ensuring valid data + +The form template uses dynamic data binding of metadata to render the form without making any hardcoded assumptions about specific questions. +It adds both control metadata and validation criteria dynamically. + +To ensure valid input, the _Save_ button is disabled until the form is in a valid state. +When the form is valid, click _Save_ and the application renders the current form values as JSON. + +The following figure shows the final form. + +Dynamic-Form + +## Next steps + + + + + diff --git a/adev-ja/src/content/guide/forms/dynamic-forms.md b/adev-ja/src/content/guide/forms/dynamic-forms.md index 60d0de0af3..216febb61d 100644 --- a/adev-ja/src/content/guide/forms/dynamic-forms.md +++ b/adev-ja/src/content/guide/forms/dynamic-forms.md @@ -1,143 +1,143 @@ -# Building dynamic forms +# 動的フォームの作成 -Many forms, such as questionnaires, can be very similar to one another in format and intent. -To make it faster and easier to generate different versions of such a form, you can create a _dynamic form template_ based on metadata that describes the business object model. -Then, use the template to generate new forms automatically, according to changes in the data model. +アンケートなどの多くのフォームは、フォーマットと意図において非常に類似している場合があります。 +このようなフォームの異なるバージョンをより速く簡単に生成できるように、ビジネスオブジェクトモデルを記述するメタデータに基づいて、_動的フォームテンプレート_を作成できます。 +その後、テンプレートを使用して、データモデルの変更に応じて、新しいフォームを自動的に生成します。 -The technique is particularly useful when you have a type of form whose content must change frequently to meet rapidly changing business and regulatory requirements. -A typical use-case is a questionnaire. -You might need to get input from users in different contexts. -The format and style of the forms a user sees should remain constant, while the actual questions you need to ask vary with the context. +このテクニックは、ビジネスや規制要件の急速な変化に対応するために、コンテンツを頻繁に変更する必要があるフォームの種類を持つ場合に特に役立ちます。 +一般的なユースケースはアンケートです。 +さまざまなコンテキストでユーザーからの入力を受け取る必要がある場合があります。 +ユーザーが見ているフォームのフォーマットとスタイルは一定に保つ必要がありますが、実際に尋ねる必要がある質問はコンテキストによって異なります。 -In this tutorial you will build a dynamic form that presents a basic questionnaire. -You build an online application for heroes seeking employment. -The agency is constantly tinkering with the application process, but by using the dynamic form -you can create the new forms on the fly without changing the application code. +このチュートリアルでは、基本的なアンケートを表示する動的フォームを作成します。 +雇用を求めるヒーローのためのオンラインアプリケーションを構築します。 +エージェンシーは常にアプリケーションプロセスをいじっていますが、 +動的フォームを使用することでアプリケーションコードを変更せずに新しいフォームをオンザフライで作成できます。 -The tutorial walks you through the following steps. +このチュートリアルでは、次の手順について説明します。 -1. Enable reactive forms for a project. -1. Establish a data model to represent form controls. -1. Populate the model with sample data. -1. Develop a component to create form controls dynamically. +1. プロジェクトでリアクティブフォームを有効にする。 +1. フォームコントロールを表すデータモデルを確立する。 +1. サンプルデータでモデルを埋める。 +1. フォームコントロールを動的に作成するコンポーネントを開発する。 -The form you create uses input validation and styling to improve the user experience. -It has a Submit button that is only enabled when all user input is valid, and flags invalid input with color coding and error messages. +作成するフォームでは、入力検証とスタイリングを使用してユーザー体験を向上させます。 +すべてのユーザー入力が有効な場合にのみ有効になる送信ボタンがあり、無効な入力を色分けとエラーメッセージでフラグ付けします。 -The basic version can evolve to support a richer variety of questions, more graceful rendering, and superior user experience. +この基本バージョンは、より多くの種類の質問、より洗練されたレンダリング、優れたユーザー体験をサポートするように進化させることができます。 -## Enable reactive forms for your project +## プロジェクトでリアクティブフォームを有効にする -Dynamic forms are based on reactive forms. +動的フォームはリアクティブフォームに基づいています。 -To give the application access reactive forms directives, import `ReactiveFormsModule` from the `@angular/forms` library into the necessary components. +アプリケーションにリアクティブフォームディレクティブへのアクセス権を与えるには、必要なコンポーネントに `@angular/forms` ライブラリから `ReactiveFormsModule` をインポートします。 -The following code from the example shows the setup in the root module. +例からの次のコードは、ルートモジュールでのセットアップを示しています。 -## Create a form object model +## フォームオブジェクトモデルを作成する -A dynamic form requires an object model that can describe all scenarios needed by the form functionality. -The example hero-application form is a set of questions — that is, each control in the form must ask a question and accept an answer. +動的フォームには、フォーム機能に必要なすべてのシナリオを記述できるオブジェクトモデルが必要です。 +例のヒーローアプリケーションフォームは、一連の質問です。つまり、フォーム内の各コントロールは質問をし、回答を受け入れる必要があります。 -The data model for this type of form must represent a question. -The example includes the `DynamicFormQuestionComponent`, which defines a question as the fundamental object in the model. +このタイプのフォームのデータモデルは、質問を表す必要があります。 +例には、`DynamicFormQuestionComponent` が含まれており、質問をモデルの基本オブジェクトとして定義しています。 -The following `QuestionBase` is a base class for a set of controls that can represent the question and its answer in the form. +次の `QuestionBase` は、フォーム内の質問とその回答を表すことができる一連のコントロールのベースクラスです。 -### Define control classes +### コントロールクラスを定義する -From this base, the example derives two new classes, `TextboxQuestion` and `DropdownQuestion`, that represent different control types. -When you create the form template in the next step, you instantiate these specific question types in order to render the appropriate controls dynamically. +このベースから、例では、異なるコントロールタイプを表す `TextboxQuestion` と `DropdownQuestion` の2つの新しいクラスを派生させます。 +次のステップでフォームテンプレートを作成するときは、適切なコントロールを動的にレンダリングするために、これらの特定の質問タイプをインスタンス化します。 -The `TextboxQuestion` control type is represented in a form template using an `` element. It presents a question and lets users enter input. The `type` attribute of the element is defined based on the `type` field specified in the `options` argument (for example `text`, `email`, `url`). +`TextboxQuestion` コントロールタイプは、フォームテンプレートでは `` 要素を使用して表されます。質問を表示し、ユーザーが入力をできるようにします。要素の `type` 属性は、`options` 引数で指定された `type` フィールドに基づいて定義されます(例:`text`、`email`、`url`)。 -The `DropdownQuestion` control type presents a list of choices in a select box. +`DropdownQuestion` コントロールタイプは、選択ボックスに選択肢のリストを表示します。 - + -### Compose form groups +### フォームグループを構成する -A dynamic form uses a service to create grouped sets of input controls, based on the form model. -The following `QuestionControlService` collects a set of `FormGroup` instances that consume the metadata from the question model. -You can specify default values and validation rules. +動的フォームは、サービスを使用して、質問モデルのメタデータに基づいて、入力コントロールのグループ化されたセットを作成します。 +次の `QuestionControlService` は、質問モデルからメタデータを使用する `FormGroup` インスタンスのセットを収集します。 +デフォルト値と検証ルールを指定できます。 -## Compose dynamic form contents +## 動的フォームコンテンツを構成する -The dynamic form itself is represented by a container component, which you add in a later step. -Each question is represented in the form component's template by an `` tag, which matches an instance of `DynamicFormQuestionComponent`. +動的フォーム自体は、後で追加するコンテナーコンポーネントで表されます。 +各質問は、フォームコンポーネントのテンプレートで、`DynamicFormQuestionComponent` のインスタンスと一致する `` タグで表されます。 -The `DynamicFormQuestionComponent` is responsible for rendering the details of an individual question based on values in the data-bound question object. -The form relies on a [`[formGroup]` directive](api/forms/FormGroupDirective "API reference") to connect the template HTML to the underlying control objects. -The `DynamicFormQuestionComponent` creates form groups and populates them with controls defined in the question model, specifying display and validation rules. +`DynamicFormQuestionComponent` は、データバインドされた質問オブジェクトの値に基づいて、個々の質問の詳細をレンダリングする責任があります。 +フォームは、[`[formGroup]` ディレクティブ](api/forms/FormGroupDirective "API リファレンス") に依存して、テンプレートHTMLを基礎となるコントロールオブジェクトに接続します。 +`DynamicFormQuestionComponent` は、フォームグループを作成し、質問モデルにより定義されたコントロールでそれらを埋め、表示と検証ルールを指定します。 -The goal of the `DynamicFormQuestionComponent` is to present question types defined in your model. -You only have two types of questions at this point but you can imagine many more. -The `ngSwitch` statement in the template determines which type of question to display. -The switch uses directives with the [`formControlName`](api/forms/FormControlName "FormControlName directive API reference") and [`formGroup`](api/forms/FormGroupDirective "FormGroupDirective API reference") selectors. -Both directives are defined in `ReactiveFormsModule`. +`DynamicFormQuestionComponent` の目標は、モデルで定義された質問タイプを提示することです。 +現時点では質問タイプが2つしかありませんが、さらに多くのタイプが考えられます。 +テンプレートの `ngSwitch` ステートメントは、表示する質問タイプを決定します。 +スイッチは、[`formControlName`](api/forms/FormControlName "FormControlName ディレクティブ API リファレンス") と [`formGroup`](api/forms/FormGroupDirective "FormGroupDirective API リファレンス") セレクターを持つディレクティブを使用します。 +両方のディレクティブは `ReactiveFormsModule` で定義されています。 -### Supply data +### データを供給する -Another service is needed to supply a specific set of questions from which to build an individual form. -For this exercise you create the `QuestionService` to supply this array of questions from the hard-coded sample data. -In a real-world app, the service might fetch data from a backend system. -The key point, however, is that you control the hero job-application questions entirely through the objects returned from `QuestionService`. -To maintain the questionnaire as requirements change, you only need to add, update, and remove objects from the `questions` array. +個々のフォームを構築するために、特定の質問セットを供給するサービスも必要です。 +この演習では、ハードコードされたサンプルデータからこの質問の配列を供給する `QuestionService` を作成します。 +実際のアプリケーションでは、サービスはバックエンドシステムからデータを取得する可能性があります。 +ただし、重要な点は、ヒーローの求人質問を `QuestionService` から返されるオブジェクトを通じて完全に制御できることです。 +要件が変更された場合にアンケートを維持するには、`questions` 配列からオブジェクトを追加、更新、削除するだけです。 -The `QuestionService` supplies a set of questions in the form of an array bound to `@Input()` questions. +`QuestionService` は、`@Input()` questionsにバインドされた配列の形式で、質問セットを供給します。 -## Create a dynamic form template +## 動的フォームテンプレートを作成する -The `DynamicFormComponent` component is the entry point and the main container for the form, which is represented using the `` in a template. +`DynamicFormComponent` コンポーネントは、テンプレートで `` を使用して表されるフォームのエントリポイントであり、メインコンテナーです。 -The `DynamicFormComponent` component presents a list of questions by binding each one to an `` element that matches the `DynamicFormQuestionComponent`. +`DynamicFormComponent` コンポーネントは、各質問を、`DynamicFormQuestionComponent` と一致する `` 要素にバインドすることによって、質問のリストを表示します。 -### Display the form +### フォームを表示する -To display an instance of the dynamic form, the `AppComponent` shell template passes the `questions` array returned by the `QuestionService` to the form container component, ``. +動的フォームのインスタンスを表示するには、`AppComponent` シェルテンプレートは、`QuestionService` から返された `questions` 配列を、フォームコンテナーコンポーネント `` に渡します。 -This separation of model and data lets you repurpose the components for any type of survey, as long as it's compatible with the _question_ object model. +このモデルとデータの分離により、_質問_ オブジェクトモデルと互換性がある限り、あらゆるタイプのアンケートにコンポーネントを再利用できます。 -### Ensuring valid data +### 有効なデータを確保する -The form template uses dynamic data binding of metadata to render the form without making any hardcoded assumptions about specific questions. -It adds both control metadata and validation criteria dynamically. +フォームテンプレートは、特定の質問についてハードコードされた仮定を一切行わずに、メタデータの動的データバインドを使用してフォームをレンダリングします。 +コントロールメタデータと検証基準の両方を動的に追加します。 -To ensure valid input, the _Save_ button is disabled until the form is in a valid state. -When the form is valid, click _Save_ and the application renders the current form values as JSON. +有効な入力を確保するために、フォームが有効な状態になるまで、_保存_ ボタンは無効になっています。 +フォームが有効になったら、_保存_ をクリックすると、アプリケーションは現在のフォーム値をJSONとしてレンダリングします。 -The following figure shows the final form. +次の図は、最終的なフォームを示しています。 Dynamic-Form -## Next steps +## 次のステップ - - + + diff --git a/adev-ja/src/content/guide/forms/form-validation.en.md b/adev-ja/src/content/guide/forms/form-validation.en.md new file mode 100644 index 0000000000..f72fca26eb --- /dev/null +++ b/adev-ja/src/content/guide/forms/form-validation.en.md @@ -0,0 +1,347 @@ +# Validating form input + +You can improve overall data quality by validating user input for accuracy and completeness. +This page shows how to validate user input from the UI and display useful validation messages, in both reactive and template-driven forms. + +## Validating input in template-driven forms + +To add validation to a template-driven form, you add the same validation attributes as you would with [native HTML form validation](https://developer.mozilla.org/docs/Web/Guide/HTML/HTML5/Constraint_validation). +Angular uses directives to match these attributes with validator functions in the framework. + +Every time the value of a form control changes, Angular runs validation and generates either a list of validation errors that results in an `INVALID` status, or null, which results in a VALID status. + +You can then inspect the control's state by exporting `ngModel` to a local template variable. +The following example exports `NgModel` into a variable called `name`: + + + +Notice the following features illustrated by the example. + +* The `` element carries the HTML validation attributes: `required` and `minlength`. + It also carries a custom validator directive, `forbiddenName`. + For more information, see the [Custom validators](#defining-custom-validators) section. + +* `#name="ngModel"` exports `NgModel` into a local variable called `name`. + `NgModel` mirrors many of the properties of its underlying `FormControl` instance, so you can use this in the template to check for control states such as `valid` and `dirty`. + For a full list of control properties, see the [AbstractControl](api/forms/AbstractControl) API reference. + + * The `*ngIf` on the `
` element reveals a set of nested message `divs` but only if the `name` is invalid and the control is either `dirty` or `touched`. + + * Each nested `
` can present a custom message for one of the possible validation errors. + There are messages for `required`, `minlength`, and `forbiddenName`. + +HELPFUL: To prevent the validator from displaying errors before the user has a chance to edit the form, you should check for either the `dirty` or `touched` states in a control. + +* When the user changes the value in the watched field, the control is marked as "dirty" +* When the user blurs the form control element, the control is marked as "touched" + +## Validating input in reactive forms + +In a reactive form, the source of truth is the component class. +Instead of adding validators through attributes in the template, you add validator functions directly to the form control model in the component class. +Angular then calls these functions whenever the value of the control changes. + +### Validator functions + +Validator functions can be either synchronous or asynchronous. + +| Validator type | Details | +|:--- |:--- | +| Sync validators | Synchronous functions that take a control instance and immediately return either a set of validation errors or `null`. Pass these in as the second argument when you instantiate a `FormControl`. | +| Async validators | Asynchronous functions that take a control instance and return a Promise or Observable that later emits a set of validation errors or `null`. Pass these in as the third argument when you instantiate a `FormControl`. | + +For performance reasons, Angular only runs async validators if all sync validators pass. +Each must complete before errors are set. + +### Built-in validator functions + +You can choose to [write your own validator functions](#defining-custom-validators), or you can use some of Angular's built-in validators. + +The same built-in validators that are available as attributes in template-driven forms, such as `required` and `minlength`, are all available to use as functions from the `Validators` class. +For a full list of built-in validators, see the [Validators](api/forms/Validators) API reference. + +To update the actor form to be a reactive form, use some of the same +built-in validators —this time, in function form, as in the following example. + + + +In this example, the `name` control sets up two built-in validators —`Validators.required` and `Validators.minLength(4)`— and one custom validator, `forbiddenNameValidator`. + +All of these validators are synchronous, so they are passed as the second argument. +Notice that you can support multiple validators by passing the functions in as an array. + +This example also adds a few getter methods. +In a reactive form, you can always access any form control through the `get` method on its parent group, but sometimes it's useful to define getters as shorthand for the template. + +If you look at the template for the `name` input again, it is fairly similar to the template-driven example. + + + +This form differs from the template-driven version in that it no longer exports any directives. Instead, it uses the `name` getter defined in the component class. + +Notice that the `required` attribute is still present in the template. Although it's not necessary for validation, it should be retained for accessibility purposes. + +## Defining custom validators + +The built-in validators don't always match the exact use case of your application, so you sometimes need to create a custom validator. + +Consider the `forbiddenNameValidator` function from the previous example. +Here's what the definition of that function looks like. + + + +The function is a factory that takes a regular expression to detect a *specific* forbidden name and returns a validator function. + +In this sample, the forbidden name is "bob", so the validator rejects any actor name containing "bob". +Elsewhere it could reject "alice" or any name that the configuring regular expression matches. + +The `forbiddenNameValidator` factory returns the configured validator function. +That function takes an Angular control object and returns *either* null if the control value is valid *or* a validation error object. +The validation error object typically has a property whose name is the validation key, `'forbiddenName'`, and whose value is an arbitrary dictionary of values that you could insert into an error message, `{name}`. + +Custom async validators are similar to sync validators, but they must instead return a Promise or observable that later emits null or a validation error object. +In the case of an observable, the observable must complete, at which point the form uses the last value emitted for validation. + +### Adding custom validators to reactive forms + +In reactive forms, add a custom validator by passing the function directly to the `FormControl`. + + + +### Adding custom validators to template-driven forms + +In template-driven forms, add a directive to the template, where the directive wraps the validator function. +For example, the corresponding `ForbiddenValidatorDirective` serves as a wrapper around the `forbiddenNameValidator`. + +Angular recognizes the directive's role in the validation process because the directive registers itself with the `NG_VALIDATORS` provider, as shown in the following example. +`NG_VALIDATORS` is a predefined provider with an extensible collection of validators. + + + +The directive class then implements the `Validator` interface, so that it can easily integrate with Angular forms. +Here is the rest of the directive to help you get an idea of how it all comes together. + + + +Once the `ForbiddenValidatorDirective` is ready, you can add its selector, `appForbiddenName`, to any input element to activate it. +For example: + + + +HELPFUL: Notice that the custom validation directive is instantiated with `useExisting` rather than `useClass`. +The registered validator must be *this instance* of the `ForbiddenValidatorDirective` —the instance in the form with its `forbiddenName` property bound to "bob". + +If you were to replace `useExisting` with `useClass`, then you'd be registering a new class instance, one that doesn't have a `forbiddenName`. + +## Control status CSS classes + +Angular automatically mirrors many control properties onto the form control element as CSS classes. +Use these classes to style form control elements according to the state of the form. +The following classes are currently supported. + +* `.ng-valid` +* `.ng-invalid` +* `.ng-pending` +* `.ng-pristine` +* `.ng-dirty` +* `.ng-untouched` +* `.ng-touched` +* `.ng-submitted` \(enclosing form element only\) + +In the following example, the actor form uses the `.ng-valid` and `.ng-invalid` classes to +set the color of each form control's border. + + + +## Cross-field validation + +A cross-field validator is a [custom validator](#defining-custom-validators "Read about custom validators") that compares the values of different fields in a form and accepts or rejects them in combination. +For example, you might have a form that offers mutually incompatible options, so that if the user can choose A or B, but not both. +Some field values might also depend on others; a user might be allowed to choose B only if A is also chosen. + +The following cross validation examples show how to do the following: + +* Validate reactive or template-based form input based on the values of two sibling controls, +* Show a descriptive error message after the user interacted with the form and the validation failed. + +The examples use cross-validation to ensure that actors do not reuse the same name in their role by filling out the Actor Form. +The validators do this by checking that the actor names and roles do not match. + +### Adding cross-validation to reactive forms + +The form has the following structure: + + + +const actorForm = new FormGroup({ + 'name': new FormControl(), + 'role': new FormControl(), + 'skill': new FormControl() +}); + + + +Notice that the `name` and `role` are sibling controls. +To evaluate both controls in a single custom validator, you must perform the validation in a common ancestor control: the `FormGroup`. +You query the `FormGroup` for its child controls so that you can compare their values. + +To add a validator to the `FormGroup`, pass the new validator in as the second argument on creation. + + + +const actorForm = new FormGroup({ + 'name': new FormControl(), + 'role': new FormControl(), + 'skill': new FormControl() +}, { validators: unambiguousRoleValidator }); + + + +The validator code is as follows. + + + +The `unambiguousRoleValidator` validator implements the `ValidatorFn` interface. +It takes an Angular control object as an argument and returns either null if the form is valid, or `ValidationErrors` otherwise. + +The validator retrieves the child controls by calling the `FormGroup`'s [get](api/forms/AbstractControl#get) method, then compares the values of the `name` and `role` controls. + +If the values do not match, the role is unambiguous, both are valid, and the validator returns null. +If they do match, the actor's role is ambiguous and the validator must mark the form as invalid by returning an error object. + +To provide better user experience, the template shows an appropriate error message when the form is invalid. + + + +This `*ngIf` displays the error if the `FormGroup` has the cross validation error returned by the `unambiguousRoleValidator` validator, but only if the user finished [interacting with the form](#control-status-css-classes). + +### Adding cross-validation to template-driven forms + +For a template-driven form, you must create a directive to wrap the validator function. +You provide that directive as the validator using the [`NG_VALIDATORS` token](/api/forms/NG_VALIDATORS), as shown in the following example. + + + +You must add the new directive to the HTML template. +Because the validator must be registered at the highest level in the form, the following template puts the directive on the `form` tag. + + + +To provide better user experience, an appropriate error message appears when the form is invalid. + + + +This is the same in both template-driven and reactive forms. + +## Creating asynchronous validators + +Asynchronous validators implement the `AsyncValidatorFn` and `AsyncValidator` interfaces. +These are very similar to their synchronous counterparts, with the following differences. + +* The `validate()` functions must return a Promise or an observable, +* The observable returned must be finite, meaning it must complete at some point. + To convert an infinite observable into a finite one, pipe the observable through a filtering operator such as `first`, `last`, `take`, or `takeUntil`. + +Asynchronous validation happens after the synchronous validation, and is performed only if the synchronous validation is successful. +This check lets forms avoid potentially expensive async validation processes \(such as an HTTP request\) if the more basic validation methods have already found invalid input. + +After asynchronous validation begins, the form control enters a `pending` state. +Inspect the control's `pending` property and use it to give visual feedback about the ongoing validation operation. + +A common UI pattern is to show a spinner while the async validation is being performed. +The following example shows how to achieve this in a template-driven form. + + + + + + + + +### Implementing a custom async validator + +In the following example, an async validator ensures that actors are cast for a role that is not already taken. +New actors are constantly auditioning and old actors are retiring, so the list of available roles cannot be retrieved ahead of time. +To validate the potential role entry, the validator must initiate an asynchronous operation to consult a central database of all currently cast actors. + +The following code creates the validator class, `UniqueRoleValidator`, which implements the `AsyncValidator` interface. + + + +The constructor injects the `ActorsService`, which defines the following interface. + + +interface ActorsService { + isRoleTaken: (role: string) => Observable; +} + + +In a real world application, the `ActorsService` would be responsible for making an HTTP request to the actor database to check if the role is available. +From the validator's point of view, the actual implementation of the service is not important, so the example can just code against the `ActorsService` interface. + +As the validation begins, the `UnambiguousRoleValidator` delegates to the `ActorsService` `isRoleTaken()` method with the current control value. +At this point the control is marked as `pending` and remains in this state until the observable chain returned from the `validate()` method completes. + +The `isRoleTaken()` method dispatches an HTTP request that checks if the role is available, and returns `Observable` as the result. +The `validate()` method pipes the response through the `map` operator and transforms it into a validation result. + +The method then, like any validator, returns `null` if the form is valid, and `ValidationErrors` if it is not. +This validator handles any potential errors with the `catchError` operator. +In this case, the validator treats the `isRoleTaken()` error as a successful validation, because failure to make a validation request does not necessarily mean that the role is invalid. +You could handle the error differently and return the `ValidationError` object instead. + +After some time passes, the observable chain completes and the asynchronous validation is done. +The `pending` flag is set to `false`, and the form validity is updated. + +### Adding async validators to reactive forms + +To use an async validator in reactive forms, begin by injecting the validator into the constructor of the component class. + + + +Then, pass the validator function directly to the `FormControl` to apply it. + +In the following example, the `validate` function of `UnambiguousRoleValidator` is applied to `roleControl` by passing it to the control's `asyncValidators` option and binding it to the instance of `UnambiguousRoleValidator` that was injected into `ActorFormReactiveComponent`. +The value of `asyncValidators` can be either a single async validator function, or an array of functions. +To learn more about `FormControl` options, see the [AbstractControlOptions](api/forms/AbstractControlOptions) API reference. + + + +### Adding async validators to template-driven forms + +To use an async validator in template-driven forms, create a new directive and register the `NG_ASYNC_VALIDATORS` provider on it. + +In the example below, the directive injects the `UniqueRoleValidator` class that contains the actual validation logic and invokes it in the `validate` function, triggered by Angular when validation should happen. + + + +Then, as with synchronous validators, add the directive's selector to an input to activate it. + + + +### Optimizing performance of async validators + +By default, all validators run after every form value change. +With synchronous validators, this does not normally have a noticeable impact on application performance. +Async validators, however, commonly perform some kind of HTTP request to validate the control. +Dispatching an HTTP request after every keystroke could put a strain on the backend API, and should be avoided if possible. + +You can delay updating the form validity by changing the `updateOn` property from `change` (default) to `submit` or `blur`. + +With template-driven forms, set the property in the template. + + + + + +With reactive forms, set the property in the `FormControl` instance. + + +new FormControl('', {updateOn: 'blur'}); + + +## Interaction with native HTML form validation + +By default, Angular disables [native HTML form validation](https://developer.mozilla.org/docs/Web/Guide/HTML/Constraint_validation) by adding the `novalidate` attribute on the enclosing `
` and uses directives to match these attributes with validator functions in the framework. +If you want to use native validation **in combination** with Angular-based validation, you can re-enable it with the `ngNativeValidate` directive. +See the [API docs](api/forms/NgForm#native-dom-validation-ui) for details. diff --git a/adev-ja/src/content/guide/forms/form-validation.md b/adev-ja/src/content/guide/forms/form-validation.md index f72fca26eb..dab636666e 100644 --- a/adev-ja/src/content/guide/forms/form-validation.md +++ b/adev-ja/src/content/guide/forms/form-validation.md @@ -1,143 +1,143 @@ -# Validating form input +# フォーム入力の検証 -You can improve overall data quality by validating user input for accuracy and completeness. -This page shows how to validate user input from the UI and display useful validation messages, in both reactive and template-driven forms. +正確性と完全性を確保するために、ユーザー入力を検証することで、データ品質を全体的に向上させることができます。 +このページでは、UIからのユーザー入力を検証し、リアクティブフォームとテンプレート駆動フォームの両方で、役立つ検証メッセージを表示する方法について説明します。 -## Validating input in template-driven forms +## テンプレート駆動フォームでの入力検証 -To add validation to a template-driven form, you add the same validation attributes as you would with [native HTML form validation](https://developer.mozilla.org/docs/Web/Guide/HTML/HTML5/Constraint_validation). -Angular uses directives to match these attributes with validator functions in the framework. +テンプレート駆動フォームに検証を追加するには、[ネイティブHTMLフォーム検証](https://developer.mozilla.org/docs/Web/Guide/HTML/HTML5/Constraint_validation)の場合と同じように、検証属性を追加します。 +Angularは、これらの属性をフレームワーク内のバリデーター関数と一致させるためにディレクティブを使用します。 -Every time the value of a form control changes, Angular runs validation and generates either a list of validation errors that results in an `INVALID` status, or null, which results in a VALID status. +フォームコントロールの値が変更されるたびに、Angularは検証し、検証エラーのリスト(`INVALID`ステータスをもたらす)または`null`(`VALID`ステータスをもたらす)を生成します。 -You can then inspect the control's state by exporting `ngModel` to a local template variable. -The following example exports `NgModel` into a variable called `name`: +その後、`ngModel`をローカルテンプレート変数にエクスポートすることで、コントロールの状態を調べることができます。 +次の例では、`NgModel`を`name`という変数にエクスポートします。 -Notice the following features illustrated by the example. +例で示されている次の機能に注目してください。 -* The `` element carries the HTML validation attributes: `required` and `minlength`. - It also carries a custom validator directive, `forbiddenName`. - For more information, see the [Custom validators](#defining-custom-validators) section. +* ``要素には、HTML検証属性(`required`と`minlength`)があります。 + また、カスタムバリデーターディレクティブ`forbiddenName`もあります。 + 詳細については、[カスタムバリデーター](#defining-custom-validators)セクションを参照してください。 -* `#name="ngModel"` exports `NgModel` into a local variable called `name`. - `NgModel` mirrors many of the properties of its underlying `FormControl` instance, so you can use this in the template to check for control states such as `valid` and `dirty`. - For a full list of control properties, see the [AbstractControl](api/forms/AbstractControl) API reference. +* `#name="ngModel"`は、`NgModel`を`name`というローカル変数にエクスポートします。 + `NgModel`は、基になる`FormControl`インスタンスの多くのプロパティをミラーリングしているため、テンプレート内でこれを使用して、`valid`や`dirty`などのコントロールの状態を確認できます。 + コントロールプロパティの完全なリストについては、[AbstractControl](api/forms/AbstractControl) APIリファレンスを参照してください。 - * The `*ngIf` on the `
` element reveals a set of nested message `divs` but only if the `name` is invalid and the control is either `dirty` or `touched`. + * `
`要素の`*ngIf`は、入れ子になったメッセージの`div`のセットを明らかにしますが、`name`が無効で、コントロールが`dirty`または`touched`の場合のみです。 - * Each nested `
` can present a custom message for one of the possible validation errors. - There are messages for `required`, `minlength`, and `forbiddenName`. + * 各入れ子になった`
`は、考えられる検証エラーのいずれかについて、カスタムメッセージを表示できます。 + `required`、`minlength`、`forbiddenName`のメッセージがあります。 -HELPFUL: To prevent the validator from displaying errors before the user has a chance to edit the form, you should check for either the `dirty` or `touched` states in a control. +HELPFUL: ユーザーがフォームを編集する機会がある前に、バリデーターがエラーを表示しないようにするには、コントロールの`dirty`または`touched`状態のいずれかをチェックする必要があります。 -* When the user changes the value in the watched field, the control is marked as "dirty" -* When the user blurs the form control element, the control is marked as "touched" +* ユーザーが監視対象のフィールドの値を変更すると、コントロールは「dirty」としてマークされます。 +* ユーザーがフォームコントロール要素からフォーカスを外すと、コントロールは「touched」としてマークされます。 -## Validating input in reactive forms +## リアクティブフォームでの入力検証 -In a reactive form, the source of truth is the component class. -Instead of adding validators through attributes in the template, you add validator functions directly to the form control model in the component class. -Angular then calls these functions whenever the value of the control changes. +リアクティブフォームでは、真実の源はコンポーネントクラスです。 +テンプレートで属性を通じてバリデーターを追加する代わりに、コンポーネントクラスのフォームコントロールモデルに直接バリデーター関数を追加します。 +その後、Angularは、コントロールの値が変更されるたびにこれらの関数を呼び出します。 -### Validator functions +### バリデーター関数 -Validator functions can be either synchronous or asynchronous. +バリデーター関数は、同期または非同期にすることができます。 -| Validator type | Details | +| バリデーターの種類 | 詳細 | |:--- |:--- | -| Sync validators | Synchronous functions that take a control instance and immediately return either a set of validation errors or `null`. Pass these in as the second argument when you instantiate a `FormControl`. | -| Async validators | Asynchronous functions that take a control instance and return a Promise or Observable that later emits a set of validation errors or `null`. Pass these in as the third argument when you instantiate a `FormControl`. | +| 同期バリデーター | コントロールインスタンスを受け取り、検証エラーのセットまたは`null`をすぐに返す同期関数。`FormControl`をインスタンス化する際に、第2引数として渡します。 | +| 非同期バリデーター | コントロールインスタンスを受け取り、後で検証エラーのセットまたは`null`を発行するPromiseまたはObservableを返す非同期関数。`FormControl`をインスタンス化する際に、第3引数として渡します。 | -For performance reasons, Angular only runs async validators if all sync validators pass. -Each must complete before errors are set. +パフォーマンス上の理由から、Angularは、すべての同期バリデーターが合格した場合にのみ非同期バリデーターを実行します。 +各バリデーターは、エラーが設定される前に完了する必要があります。 -### Built-in validator functions +### 組み込みのバリデーター関数 -You can choose to [write your own validator functions](#defining-custom-validators), or you can use some of Angular's built-in validators. +[独自のバリデーター関数](#defining-custom-validators)を作成することも、Angularの組み込みのバリデーターのいくつかを使用することもできます。 -The same built-in validators that are available as attributes in template-driven forms, such as `required` and `minlength`, are all available to use as functions from the `Validators` class. -For a full list of built-in validators, see the [Validators](api/forms/Validators) API reference. +`required`や`minlength`など、テンプレート駆動フォームで属性として使用できるものと同じ組み込みバリデーターはすべて、`Validators`クラスから関数として使用できます。 +組み込みのバリデーターの完全なリストについては、[Validators](api/forms/Validators) APIリファレンスを参照してください。 -To update the actor form to be a reactive form, use some of the same -built-in validators —this time, in function form, as in the following example. +アクターフォームをリアクティブフォームに更新するには、いくつかの組み込みバリデーターを使用します。 +今回は、関数形式で、次の例のようにします。 -In this example, the `name` control sets up two built-in validators —`Validators.required` and `Validators.minLength(4)`— and one custom validator, `forbiddenNameValidator`. +この例では、`name`コントロールは、2つの組み込みバリデーター(`Validators.required`と`Validators.minLength(4)`)と、1つのカスタムバリデーター`forbiddenNameValidator`を設定しています。 -All of these validators are synchronous, so they are passed as the second argument. -Notice that you can support multiple validators by passing the functions in as an array. +これらすべてのバリデーターは同期であるため、第2引数として渡されます。 +関数を配列として渡すことで、複数のバリデーターをサポートできることに注意してください。 -This example also adds a few getter methods. -In a reactive form, you can always access any form control through the `get` method on its parent group, but sometimes it's useful to define getters as shorthand for the template. +この例では、いくつかのゲッターメソッドも追加されています。 +リアクティブフォームでは、常に親グループの`get`メソッドを通じて任意のフォームコントロールにアクセスできますが、テンプレートの省略形としてゲッターを定義することが便利な場合があります。 -If you look at the template for the `name` input again, it is fairly similar to the template-driven example. +`name`入力のテンプレートをもう一度見ると、テンプレート駆動の例とかなり似ています。 -This form differs from the template-driven version in that it no longer exports any directives. Instead, it uses the `name` getter defined in the component class. +このフォームは、テンプレート駆動バージョンとは、ディレクティブをエクスポートしなくなった点が異なります。代わりに、コンポーネントクラスで定義された`name`ゲッターを使用します。 -Notice that the `required` attribute is still present in the template. Although it's not necessary for validation, it should be retained for accessibility purposes. +`required`属性は、テンプレートにまだ存在することに注意してください。検証には必要ありませんが、アクセシビリティの目的で保持する必要があります。 -## Defining custom validators +## カスタムバリデーターの定義 {#defining-custom-validators} -The built-in validators don't always match the exact use case of your application, so you sometimes need to create a custom validator. +組み込みのバリデーターは、アプリケーションのユースケースに常に一致するわけではありません。そのため、カスタムバリデーターを作成する必要がある場合があります。 -Consider the `forbiddenNameValidator` function from the previous example. -Here's what the definition of that function looks like. +前の例の`forbiddenNameValidator`関数を考えてみてください。 +その関数の定義は次のようになります。 -The function is a factory that takes a regular expression to detect a *specific* forbidden name and returns a validator function. +関数は、*特定の*禁止されている名前を検出するための正規表現を受け取り、バリデーター関数を返すファクトリです。 -In this sample, the forbidden name is "bob", so the validator rejects any actor name containing "bob". -Elsewhere it could reject "alice" or any name that the configuring regular expression matches. +このサンプルでは、禁止されている名前は「bob」なので、バリデーターは「bob」を含むアクター名をすべて拒否します。 +他の場所では、「alice」や、構成された正規表現に一致する名前を拒否することもできます。 -The `forbiddenNameValidator` factory returns the configured validator function. -That function takes an Angular control object and returns *either* null if the control value is valid *or* a validation error object. -The validation error object typically has a property whose name is the validation key, `'forbiddenName'`, and whose value is an arbitrary dictionary of values that you could insert into an error message, `{name}`. +`forbiddenNameValidator`ファクトリは、構成されたバリデーター関数を返します。 +その関数はAngularコントロールオブジェクトを受け取り、コントロール値が有効な場合は`null`を返し、無効な場合は検証エラーオブジェクトを返します。 +検証エラーオブジェクトには通常、検証キーの名前である`'forbiddenName'`というプロパティと、エラーメッセージに挿入できる任意の値の辞書である`{name}`という値を持つプロパティがあります。 -Custom async validators are similar to sync validators, but they must instead return a Promise or observable that later emits null or a validation error object. -In the case of an observable, the observable must complete, at which point the form uses the last value emitted for validation. +カスタム非同期バリデーターは同期バリデーターに似ていますが、代わりに後で`null`または検証エラーオブジェクトを発行するPromiseまたはオブザーバブルを返す必要があります。 +オブザーバブルの場合、オブザーバブルは完了する必要があります。その時点で、フォームは最後の発行された値を検証に使用します。 -### Adding custom validators to reactive forms +### カスタムバリデーターをリアクティブフォームに追加する -In reactive forms, add a custom validator by passing the function directly to the `FormControl`. +リアクティブフォームでは、`FormControl`に直接関数を渡すことで、カスタムバリデーターを追加します。 -### Adding custom validators to template-driven forms +### カスタムバリデーターをテンプレート駆動フォームに追加する -In template-driven forms, add a directive to the template, where the directive wraps the validator function. -For example, the corresponding `ForbiddenValidatorDirective` serves as a wrapper around the `forbiddenNameValidator`. +テンプレート駆動フォームでは、テンプレートにディレクティブを追加します。ディレクティブは、バリデーター関数をラップします。 +たとえば、対応する`ForbiddenValidatorDirective`は、`forbiddenNameValidator`のラッパーとして機能します。 -Angular recognizes the directive's role in the validation process because the directive registers itself with the `NG_VALIDATORS` provider, as shown in the following example. -`NG_VALIDATORS` is a predefined provider with an extensible collection of validators. +Angularは、ディレクティブが`NG_VALIDATORS`プロバイダーに自身を登録するため、ディレクティブの検証プロセスにおける役割を認識します。次の例に示すように。 +`NG_VALIDATORS`は、拡張可能なバリデーターのコレクションを持つ、定義済みのプロバイダーです。 -The directive class then implements the `Validator` interface, so that it can easily integrate with Angular forms. -Here is the rest of the directive to help you get an idea of how it all comes together. +その後、ディレクティブクラスは`Validator`インターフェースを実装するため、Angularフォームと簡単に統合できます。 +以下は、ディレクティブ全体の概要です。 -Once the `ForbiddenValidatorDirective` is ready, you can add its selector, `appForbiddenName`, to any input element to activate it. -For example: +`ForbiddenValidatorDirective`の準備ができたら、セレクター`appForbiddenName`を入力要素に追加して、アクティブ化できます。 +たとえば、次のとおりです。 -HELPFUL: Notice that the custom validation directive is instantiated with `useExisting` rather than `useClass`. -The registered validator must be *this instance* of the `ForbiddenValidatorDirective` —the instance in the form with its `forbiddenName` property bound to "bob". +HELPFUL: カスタム検証ディレクティブが`useExisting`ではなく`useClass`でインスタンス化されていることに注意してください。 +登録されたバリデーターは、`ForbiddenValidatorDirective`の*このインスタンス*である必要があります。フォーム内のインスタンスで、`forbiddenName`プロパティが「bob」にバインドされています。 -If you were to replace `useExisting` with `useClass`, then you'd be registering a new class instance, one that doesn't have a `forbiddenName`. +`useExisting`を`useClass`に置き換えると、`forbiddenName`を持たない新しいクラスインスタンスを登録することになります。 -## Control status CSS classes +## コントロールステータスCSSクラス {#control-status-css-classes} -Angular automatically mirrors many control properties onto the form control element as CSS classes. -Use these classes to style form control elements according to the state of the form. -The following classes are currently supported. +Angularは、多くのコントロールプロパティをフォームコントロール要素にCSSクラスとして自動的にミラーリングします。 +これらのクラスを使用して、フォームの状態に応じてフォームコントロール要素のスタイルを設定します。 +現在サポートされているクラスは次のとおりです。 * `.ng-valid` * `.ng-invalid` @@ -146,30 +146,30 @@ The following classes are currently supported. * `.ng-dirty` * `.ng-untouched` * `.ng-touched` -* `.ng-submitted` \(enclosing form element only\) +* `.ng-submitted` (囲んでいるフォーム要素のみ) -In the following example, the actor form uses the `.ng-valid` and `.ng-invalid` classes to -set the color of each form control's border. +次の例では、アクターフォームは`.ng-valid`と`.ng-invalid`クラスを使用して、 +各フォームコントロールの境界線の色を設定しています。 -## Cross-field validation +## クロスフィールド検証 -A cross-field validator is a [custom validator](#defining-custom-validators "Read about custom validators") that compares the values of different fields in a form and accepts or rejects them in combination. -For example, you might have a form that offers mutually incompatible options, so that if the user can choose A or B, but not both. -Some field values might also depend on others; a user might be allowed to choose B only if A is also chosen. +クロスフィールドバリデーターは、フォーム内の異なるフィールドの値を比較し、組み合わせで受け入れるか拒否する[カスタムバリデーター](#defining-custom-validators "カスタムバリデーターについて読む")です。 +たとえば、互いに非互換なオプションを提供するフォームがある場合、ユーザーはAまたはBを選択できますが、両方は選択できません。 +フィールドの値によっては、他の値に依存する場合もあります。ユーザーは、Aを選択した場合にのみBを選択できます。 -The following cross validation examples show how to do the following: +次のクロス検証の例は、次の方法を示しています。 -* Validate reactive or template-based form input based on the values of two sibling controls, -* Show a descriptive error message after the user interacted with the form and the validation failed. +* 2つの兄弟コントロールの値に基づいて、リアクティブまたはテンプレートベースのフォーム入力を検証する +* ユーザーがフォームとやり取りし、検証に失敗した場合に、説明的なエラーメッセージを表示する -The examples use cross-validation to ensure that actors do not reuse the same name in their role by filling out the Actor Form. -The validators do this by checking that the actor names and roles do not match. +これらの例では、クロス検証を使用して、アクターがアクターフォームに記入することで、役割で同じ名前を再利用しないようにしています。 +バリデーターは、アクター名と役割が一致しないことを確認することで、これを実現します。 -### Adding cross-validation to reactive forms +### クロス検証をリアクティブフォームに追加する -The form has the following structure: +フォームは、次の構造になっています。 @@ -181,11 +181,11 @@ const actorForm = new FormGroup({ -Notice that the `name` and `role` are sibling controls. -To evaluate both controls in a single custom validator, you must perform the validation in a common ancestor control: the `FormGroup`. -You query the `FormGroup` for its child controls so that you can compare their values. +`name`と`role`は兄弟コントロールであることに注意してください。 +1つのカスタムバリデーターで両方のコントロールを評価するには、共通の祖先コントロールである`FormGroup`で検証する必要があります。 +子コントロールを取得するために`FormGroup`をクエリして、値を比較します。 -To add a validator to the `FormGroup`, pass the new validator in as the second argument on creation. +`FormGroup`にバリデーターを追加するには、作成時に第2引数として新しいバリデーターを渡します。 @@ -197,59 +197,59 @@ const actorForm = new FormGroup({ -The validator code is as follows. +バリデーターのコードは次のとおりです。 -The `unambiguousRoleValidator` validator implements the `ValidatorFn` interface. -It takes an Angular control object as an argument and returns either null if the form is valid, or `ValidationErrors` otherwise. +`unambiguousRoleValidator`バリデーターは、`ValidatorFn`インターフェースを実装しています。 +これはAngularコントロールオブジェクトを引数として受け取り、フォームが有効な場合は`null`を返し、無効な場合は`ValidationErrors`を返します。 -The validator retrieves the child controls by calling the `FormGroup`'s [get](api/forms/AbstractControl#get) method, then compares the values of the `name` and `role` controls. +バリデーターは、`FormGroup`の[get](api/forms/AbstractControl#get)メソッドを呼び出して子コントロールを取得し、`name`コントロールと`role`コントロールの値を比較します。 -If the values do not match, the role is unambiguous, both are valid, and the validator returns null. -If they do match, the actor's role is ambiguous and the validator must mark the form as invalid by returning an error object. +値が一致しない場合、役割は曖昧ではなく、両方が有効で、バリデーターは`null`を返します。 +値が一致する場合、アクターの役割は曖昧で、バリデーターはエラーオブジェクトを返すことでフォームを無効にする必要があります。 -To provide better user experience, the template shows an appropriate error message when the form is invalid. +より良いユーザーエクスペリエンスを提供するために、フォームが無効な場合、テンプレートに適切なエラーメッセージが表示されます。 -This `*ngIf` displays the error if the `FormGroup` has the cross validation error returned by the `unambiguousRoleValidator` validator, but only if the user finished [interacting with the form](#control-status-css-classes). +この`*ngIf`は、`FormGroup`に`unambiguousRoleValidator`バリデーターが返したクロス検証エラーがある場合に、エラーを表示しますが、ユーザーが[フォームとやり取りを完了](#control-status-css-classes)した場合のみです。 -### Adding cross-validation to template-driven forms +### クロス検証をテンプレート駆動フォームに追加する -For a template-driven form, you must create a directive to wrap the validator function. -You provide that directive as the validator using the [`NG_VALIDATORS` token](/api/forms/NG_VALIDATORS), as shown in the following example. +テンプレート駆動フォームの場合、バリデーター関数をラップするディレクティブを作成する必要があります。 +次の例に示すように、[`NG_VALIDATORS`トークン](/api/forms/NG_VALIDATORS)を使用して、そのディレクティブをバリデーターとして提供します。 -You must add the new directive to the HTML template. -Because the validator must be registered at the highest level in the form, the following template puts the directive on the `form` tag. +新しいディレクティブをHTMLテンプレートに追加する必要があります。 +バリデーターはフォームの最上位レベルで登録する必要があるため、次のテンプレートは`form`タグにディレクティブを配置しています。 -To provide better user experience, an appropriate error message appears when the form is invalid. +より良いユーザーエクスペリエンスを提供するために、フォームが無効な場合、適切なエラーメッセージが表示されます。 -This is the same in both template-driven and reactive forms. +これは、テンプレート駆動フォームとリアクティブフォームの両方で同じです。 -## Creating asynchronous validators +## 非同期バリデーターの作成 -Asynchronous validators implement the `AsyncValidatorFn` and `AsyncValidator` interfaces. -These are very similar to their synchronous counterparts, with the following differences. +非同期バリデーターは、`AsyncValidatorFn`と`AsyncValidator`インターフェースを実装します。 +これらは、同期バリデーターと非常に似ており、次の点が異なります。 -* The `validate()` functions must return a Promise or an observable, -* The observable returned must be finite, meaning it must complete at some point. - To convert an infinite observable into a finite one, pipe the observable through a filtering operator such as `first`, `last`, `take`, or `takeUntil`. +* `validate()`関数はPromiseまたはオブザーバブルを返す必要があります。 +* 返されるオブザーバブルは有限である必要があります。つまり、ある時点で完了する必要があります。 + 無限のオブザーバブルを有限のオブザーバブルに変換するには、オブザーバブルを`first`、`last`、`take`、`takeUntil`などのフィルタリング演算子でパイプします。 -Asynchronous validation happens after the synchronous validation, and is performed only if the synchronous validation is successful. -This check lets forms avoid potentially expensive async validation processes \(such as an HTTP request\) if the more basic validation methods have already found invalid input. +非同期検証は、同期検証の後に実行され、同期検証が成功した場合にのみ実行されます。 +このチェックにより、フォームは、基本的な検証方法がすでに無効な入力を検出している場合、潜在的にコストのかかる非同期検証プロセス(HTTPリクエストなど)を回避できます。 -After asynchronous validation begins, the form control enters a `pending` state. -Inspect the control's `pending` property and use it to give visual feedback about the ongoing validation operation. +非同期検証が開始されると、フォームコントロールは`pending`状態になります。 +コントロールの`pending`プロパティを調べ、それを利用して、進行中の検証操作に関する視覚的なフィードバックを提供します。 -A common UI pattern is to show a spinner while the async validation is being performed. -The following example shows how to achieve this in a template-driven form. +一般的なUIパターンは、非同期検証の実行中にスピナーを表示することです。 +次の例は、テンプレート駆動フォームでこれを実現する方法を示しています。 @@ -258,17 +258,17 @@ The following example shows how to achieve this in a template-driven form. -### Implementing a custom async validator +### カスタム非同期バリデーターの実装 -In the following example, an async validator ensures that actors are cast for a role that is not already taken. -New actors are constantly auditioning and old actors are retiring, so the list of available roles cannot be retrieved ahead of time. -To validate the potential role entry, the validator must initiate an asynchronous operation to consult a central database of all currently cast actors. +次の例では、非同期バリデーターは、アクターがすでに割り当てられている役割にキャストされないようにします。 +新しいアクターは常にオーディションを受けており、古いアクターは引退しているため、利用可能な役割のリストを事前に取得はできません。 +潜在的な役割のエントリを検証するために、バリデーターは、現在キャストされているすべてのアクターの中央データベースを照会する非同期操作を開始する必要があります。 -The following code creates the validator class, `UniqueRoleValidator`, which implements the `AsyncValidator` interface. +次のコードは、`AsyncValidator`インターフェースを実装するバリデータークラス`UniqueRoleValidator`を作成します。 -The constructor injects the `ActorsService`, which defines the following interface. +コンストラクターは、次のインターフェースを定義する`ActorsService`を注入します。 interface ActorsService { @@ -276,72 +276,72 @@ interface ActorsService { } -In a real world application, the `ActorsService` would be responsible for making an HTTP request to the actor database to check if the role is available. -From the validator's point of view, the actual implementation of the service is not important, so the example can just code against the `ActorsService` interface. +実際のアプリケーションでは、`ActorsService`は、アクターデータベースにHTTPリクエストを送信して役割が利用可能かどうかを確認する役割を担います。 +バリデーターの観点から、サービスの実際の実装は重要でないため、例では`ActorsService`インターフェースに対してのみコードを作成できます。 -As the validation begins, the `UnambiguousRoleValidator` delegates to the `ActorsService` `isRoleTaken()` method with the current control value. -At this point the control is marked as `pending` and remains in this state until the observable chain returned from the `validate()` method completes. +検証が始まると、`UnambiguousRoleValidator`は、現在のコントロール値で`ActorsService`の`isRoleTaken()`メソッドに委任します。 +この時点で、コントロールは`pending`としてマークされ、`validate()`メソッドから返されるObservableチェーンが完了するまで、この状態を維持します。 -The `isRoleTaken()` method dispatches an HTTP request that checks if the role is available, and returns `Observable` as the result. -The `validate()` method pipes the response through the `map` operator and transforms it into a validation result. +`isRoleTaken()`メソッドは、役割が利用可能かどうかを確認するHTTPリクエストをディスパッチし、結果として`Observable`を返します。 +`validate()`メソッドは、応答を`map`演算子でパイプし、検証結果に変換します。 -The method then, like any validator, returns `null` if the form is valid, and `ValidationErrors` if it is not. -This validator handles any potential errors with the `catchError` operator. -In this case, the validator treats the `isRoleTaken()` error as a successful validation, because failure to make a validation request does not necessarily mean that the role is invalid. -You could handle the error differently and return the `ValidationError` object instead. +その後、メソッドは、他のバリデーターと同様に、フォームが有効な場合は`null`を返し、無効な場合は`ValidationErrors`を返します。 +このバリデーターは、`catchError`演算子を使用して、潜在的なエラーを処理します。 +この場合、バリデーターは`isRoleTaken()`エラーを正常な検証として扱います。検証リクエストの実行に失敗したとしても、役割が無効であるとは限りません。 +エラーを異なる方法で処理し、代わりに`ValidationError`オブジェクトを返すこともできます。 -After some time passes, the observable chain completes and the asynchronous validation is done. -The `pending` flag is set to `false`, and the form validity is updated. +しばらくすると、Observableチェーンが完了し、非同期検証が完了します。 +`pending`フラグは`false`に設定され、フォームの有効性が更新されます。 -### Adding async validators to reactive forms +### 非同期バリデーターをリアクティブフォームに追加する -To use an async validator in reactive forms, begin by injecting the validator into the constructor of the component class. +リアクティブフォームで非同期バリデーターを使用するには、最初にバリデーターをコンポーネントクラスのコンストラクターに注入します。 -Then, pass the validator function directly to the `FormControl` to apply it. +次に、バリデーター関数を`FormControl`に直接渡して、適用します。 -In the following example, the `validate` function of `UnambiguousRoleValidator` is applied to `roleControl` by passing it to the control's `asyncValidators` option and binding it to the instance of `UnambiguousRoleValidator` that was injected into `ActorFormReactiveComponent`. -The value of `asyncValidators` can be either a single async validator function, or an array of functions. -To learn more about `FormControl` options, see the [AbstractControlOptions](api/forms/AbstractControlOptions) API reference. +次の例では、`UnambiguousRoleValidator`の`validate`関数が、`roleControl`に適用されています。この関数をコントロールの`asyncValidators`オプションに渡し、`ActorFormReactiveComponent`に注入された`UnambiguousRoleValidator`のインスタンスにバインドしています。 +`asyncValidators`の値は、単一の非同期バリデーター関数、または関数の配列にすることができます。 +`FormControl`オプションの詳細については、[AbstractControlOptions](api/forms/AbstractControlOptions) APIリファレンスを参照してください。 -### Adding async validators to template-driven forms +### 非同期バリデーターをテンプレート駆動フォームに追加する -To use an async validator in template-driven forms, create a new directive and register the `NG_ASYNC_VALIDATORS` provider on it. +テンプレート駆動フォームで非同期バリデーターを使用するには、新しいディレクティブを作成し、そのディレクティブに`NG_ASYNC_VALIDATORS`プロバイダーを登録します。 -In the example below, the directive injects the `UniqueRoleValidator` class that contains the actual validation logic and invokes it in the `validate` function, triggered by Angular when validation should happen. +次の例では、ディレクティブは、実際の検証ロジックを含む`UniqueRoleValidator`クラスを注入し、検証を実行する必要があるときにAngularによってトリガーされる`validate`関数でそれを呼び出します。 -Then, as with synchronous validators, add the directive's selector to an input to activate it. +その後、同期バリデーターと同様に、ディレクティブのセレクターを入力に追加して、アクティブ化します。 -### Optimizing performance of async validators +### 非同期バリデーターのパフォーマンスの最適化 -By default, all validators run after every form value change. -With synchronous validators, this does not normally have a noticeable impact on application performance. -Async validators, however, commonly perform some kind of HTTP request to validate the control. -Dispatching an HTTP request after every keystroke could put a strain on the backend API, and should be avoided if possible. +デフォルトでは、すべてのバリデーターは、フォームの値が変更されるたびに実行されます。 +同期バリデーターの場合、これは通常、アプリケーションのパフォーマンスに目立った影響を与えません。 +ただし、非同期バリデーターは通常、コントロールを検証するために何らかのHTTPリクエストを実行します。 +キーストロークごとにHTTPリクエストをディスパッチすると、バックエンドAPIに負担がかかる可能性があり、可能な限り回避する必要があります。 -You can delay updating the form validity by changing the `updateOn` property from `change` (default) to `submit` or `blur`. +`updateOn`プロパティを`change`(デフォルト)から`submit`または`blur`に変更することで、フォームの有効性の更新を遅らせることができます。 -With template-driven forms, set the property in the template. +テンプレート駆動フォームでは、テンプレートでプロパティを設定します。 -With reactive forms, set the property in the `FormControl` instance. +リアクティブフォームでは、`FormControl`インスタンスでプロパティを設定します。 new FormControl('', {updateOn: 'blur'}); -## Interaction with native HTML form validation +## ネイティブHTMLフォーム検証との相互作用 -By default, Angular disables [native HTML form validation](https://developer.mozilla.org/docs/Web/Guide/HTML/Constraint_validation) by adding the `novalidate` attribute on the enclosing `` and uses directives to match these attributes with validator functions in the framework. -If you want to use native validation **in combination** with Angular-based validation, you can re-enable it with the `ngNativeValidate` directive. -See the [API docs](api/forms/NgForm#native-dom-validation-ui) for details. +デフォルトでは、Angularは囲んでいる``に`novalidate`属性を追加することで[ネイティブHTMLフォーム検証](https://developer.mozilla.org/docs/Web/Guide/HTML/Constraint_validation)を無効にし、これらの属性をフレームワーク内のバリデーター関数と一致させるためにディレクティブを使用します。 +ネイティブ検証を**組み合わせて**Angularベースの検証を使用したい場合は、`ngNativeValidate`ディレクティブを使用して、ネイティブ検証を再び有効にできます。 +詳細については、[APIドキュメント](api/forms/NgForm#native-dom-validation-ui)を参照してください。 diff --git a/adev-ja/src/content/guide/forms/overview.en.md b/adev-ja/src/content/guide/forms/overview.en.md new file mode 100644 index 0000000000..60a3ea327d --- /dev/null +++ b/adev-ja/src/content/guide/forms/overview.en.md @@ -0,0 +1,324 @@ + +Handling user input with forms is the cornerstone of many common applications. + + +Applications use forms to enable users to log in, to update a profile, to enter sensitive information, and to perform many other data-entry tasks. + +Angular provides two different approaches to handling user input through forms: reactive and template-driven. +Both capture user input events from the view, validate the user input, create a form model and data model to update, and provide a way to track changes. + +This guide provides information to help you decide which type of form works best for your situation. +It introduces the common building blocks used by both approaches. +It also summarizes the key differences between the two approaches, and demonstrates those differences in the context of setup, data flow, and testing. + +## Choosing an approach + +Reactive forms and template-driven forms process and manage form data differently. +Each approach offers different advantages. + +| Forms | Details | +|:--- |:--- | +| Reactive forms | Provide direct, explicit access to the underlying form's object model. Compared to template-driven forms, they are more robust: they're more scalable, reusable, and testable. If forms are a key part of your application, or you're already using reactive patterns for building your application, use reactive forms. | +| Template-driven forms | Rely on directives in the template to create and manipulate the underlying object model. They are useful for adding a simple form to an app, such as an email list signup form. They're straightforward to add to an app, but they don't scale as well as reactive forms. If you have very basic form requirements and logic that can be managed solely in the template, template-driven forms could be a good fit. | + +### Key differences + +The following table summarizes the key differences between reactive and template-driven forms. + +| | Reactive | Template-driven | +|:--- |:--- |:--- | +| [Setup of form model](#setting-up-the-form-model) | Explicit, created in component class | Implicit, created by directives | +| [Data model](#mutability-of-the-data-model) | Structured and immutable | Unstructured and mutable | +| [Data flow](#data-flow-in-forms) | Synchronous | Asynchronous | +| [Form validation](#form-validation) | Functions | Directives | + +### Scalability + +If forms are a central part of your application, scalability is very important. +Being able to reuse form models across components is critical. + +Reactive forms are more scalable than template-driven forms. +They provide direct access to the underlying form API, and use [synchronous data flow](#data-flow-in-reactive-forms) between the view and the data model, which makes creating large-scale forms easier. +Reactive forms require less setup for testing, and testing does not require deep understanding of change detection to properly test form updates and validation. + +Template-driven forms focus on simple scenarios and are not as reusable. +They abstract away the underlying form API, and use [asynchronous data flow](#data-flow-in-template-driven-forms) between the view and the data model. +The abstraction of template-driven forms also affects testing. +Tests are deeply reliant on manual change detection execution to run properly, and require more setup. + +## Setting up the form model + +Both reactive and template-driven forms track value changes between the form input elements that users interact with and the form data in your component model. +The two approaches share underlying building blocks, but differ in how you create and manage the common form-control instances. + +### Common form foundation classes + +Both reactive and template-driven forms are built on the following base classes. + +| Base classes | Details | +|:--- |:--- | +| `FormControl` | Tracks the value and validation status of an individual form control. | +| `FormGroup` | Tracks the same values and status for a collection of form controls. | +| `FormArray` | Tracks the same values and status for an array of form controls. | +| `ControlValueAccessor` | Creates a bridge between Angular `FormControl` instances and built-in DOM elements. | + +### Setup in reactive forms + +With reactive forms, you define the form model directly in the component class. +The `[formControl]` directive links the explicitly created `FormControl` instance to a specific form element in the view, using an internal value accessor. + +The following component implements an input field for a single control, using reactive forms. +In this example, the form model is the `FormControl` instance. + + + +IMPORTANT: In reactive forms, the form model is the source of truth; it provides the value and status of the form element at any given point in time, through the `[formControl]` directive on the `` element. + +### Setup in template-driven forms + +In template-driven forms, the form model is implicit, rather than explicit. +The directive `NgModel` creates and manages a `FormControl` instance for a given form element. + +The following component implements the same input field for a single control, using template-driven forms. + + + +IMPORTANT: In a template-driven form the source of truth is the template. The `NgModel` directive automatically manages the `FormControl` instance for you. + +## Data flow in forms + +When an application contains a form, Angular must keep the view in sync with the component model and the component model in sync with the view. +As users change values and make selections through the view, the new values must be reflected in the data model. +Similarly, when the program logic changes values in the data model, those values must be reflected in the view. + +Reactive and template-driven forms differ in how they handle data flowing from the user or from programmatic changes. +The following diagrams illustrate both kinds of data flow for each type of form, using the favorite-color input field defined above. + +### Data flow in reactive forms + +In reactive forms each form element in the view is directly linked to the form model (a `FormControl` instance). +Updates from the view to the model and from the model to the view are synchronous and do not depend on how the UI is rendered. + +The view-to-model diagram shows how data flows when an input field's value is changed from the view through the following steps. + +1. The user types a value into the input element, in this case the favorite color *Blue*. +1. The form input element emits an "input" event with the latest value. +1. The `ControlValueAccessor` listening for events on the form input element immediately relays the new value to the `FormControl` instance. +1. The `FormControl` instance emits the new value through the `valueChanges` observable. +1. Any subscribers to the `valueChanges` observable receive the new value. + +```mermaid +flowchart TB + U{User} + I("") + CVA(ControlValueAccessor) + FC(FormControl) + O(Observers) + U-->|Types in the input box|I + I-->|Fires the 'input' event|CVA + CVA-->|"Calls setValue() on the FormControl"|FC + FC-.->|Fires a 'valueChanges' event to observers|O +``` + +The model-to-view diagram shows how a programmatic change to the model is propagated to the view through the following steps. + +1. The user calls the `favoriteColorControl.setValue()` method, which updates the `FormControl` value. +1. The `FormControl` instance emits the new value through the `valueChanges` observable. +1. Any subscribers to the `valueChanges` observable receive the new value. +1. The control value accessor on the form input element updates the element with the new value. + +```mermaid +flowchart TB + U{User} + I() + CVA(ControlValueAccessor) + FC(FormControl) + O(Observers) + U-->|"Calls setValue() on the FormControl"|FC + FC-->|Notifies the ControlValueAccessor|CVA + FC-.->|Fires a 'valueChanges' event to observers|O + CVA-->|"Updates the value of the "|I +``` + +### Data flow in template-driven forms + +In template-driven forms, each form element is linked to a directive that manages the form model internally. + +The view-to-model diagram shows how data flows when an input field's value is changed from the view through the following steps. + +1. The user types *Blue* into the input element. +1. The input element emits an "input" event with the value *Blue*. +1. The control value accessor attached to the input triggers the `setValue()` method on the `FormControl` instance. +1. The `FormControl` instance emits the new value through the `valueChanges` observable. +1. Any subscribers to the `valueChanges` observable receive the new value. +1. The control value accessor also calls the `NgModel.viewToModelUpdate()` method which emits an `ngModelChange` event. +1. Because the component template uses two-way data binding for the `favoriteColor` property, the `favoriteColor` property in the component is updated to the value emitted by the `ngModelChange` event \(*Blue*\). + +```mermaid +flowchart TB + U{User} + I() + CVA(ControlValueAccessor) + FC(FormControl) + M(NgModel) + O(Observers) + C(Component) + P(Two-way binding) + U-->|Types in the input box|I + I-->|Fires the 'input' event|CVA + CVA-->|"Calls setValue() on the FormControl"|FC + FC-.->|Fires a 'valueChanges' event to observers|O + CVA-->|"Calls viewToModelUpdate()"|M + M-->|Emits an ngModelChange event|C + C-->|Updates the value of the two-way bound property|P +``` + +The model-to-view diagram shows how data flows from model to view when the `favoriteColor` changes from *Blue* to *Red*, through the following steps + +1. The `favoriteColor` value is updated in the component. +1. Change detection begins. +1. During change detection, the `ngOnChanges` lifecycle hook is called on the `NgModel` directive instance because the value of one of its inputs has changed. +1. The `ngOnChanges()` method queues an async task to set the value for the internal `FormControl` instance. +1. Change detection completes. +1. On the next tick, the task to set the `FormControl` instance value is executed. +1. The `FormControl` instance emits the latest value through the `valueChanges` observable. +1. Any subscribers to the `valueChanges` observable receive the new value. +1. The control value accessor updates the form input element in the view with the latest `favoriteColor` value. + +```mermaid +flowchart TB + C(Component) + P(Property bound to NgModel) + C-->|Updates the property value|P + P-->|Triggers CD|CD1 + + + subgraph CD1 [First Change Detection] + direction TB + M(NgModel) + FC(FormControl) + + M-->|Asynchronously sets FormControl value|FC + end + CD1-->|Async actions trigger a second round of Change Detection|CD2 + + subgraph CD2 [Second Change Detection] + direction TB + FC2(FormControl) + O(Observers) + CVA(ControlValueAccessor) + I("") + FC2-.->|Fires a 'valueChanges' event to observers|O + O-->|ControlValueAccessor receives valueChanges event|CVA + CVA-->|Sets the value in the control|I + end +``` + +Note: `NgModel` triggers a second change detection to avoid `ExpressionChangedAfterItHasBeenChecked` errors, because the value change originates in an input binding. + +### Mutability of the data model + +The change-tracking method plays a role in the efficiency of your application. + +| Forms | Details | +|:--- |:--- | +| Reactive forms | Keep the data model pure by providing it as an immutable data structure. Each time a change is triggered on the data model, the `FormControl` instance returns a new data model rather than updating the existing data model. This gives you the ability to track unique changes to the data model through the control's observable. Change detection is more efficient because it only needs to update on unique changes. Because data updates follow reactive patterns, you can integrate with observable operators to transform data. | +| Template-driven forms | Rely on mutability with two-way data binding to update the data model in the component as changes are made in the template. Because there are no unique changes to track on the data model when using two-way data binding, change detection is less efficient at determining when updates are required. | + +The difference is demonstrated in the previous examples that use the favorite-color input element. + +* With reactive forms, the **`FormControl` instance** always returns a new value when the control's value is updated +* With template-driven forms, the **favorite color property** is always modified to its new value + +## Form validation + +Validation is an integral part of managing any set of forms. +Whether you're checking for required fields or querying an external API for an existing username, Angular provides a set of built-in validators as well as the ability to create custom validators. + +| Forms | Details | +|:--- |:--- | +| Reactive forms | Define custom validators as **functions** that receive a control to validate | +| Template-driven forms | Tied to template **directives**, and must provide custom validator directives that wrap validation functions | + +For more information, see [Form Validation](guide/forms/form-validation#validating-input-in-reactive-forms). + +## Testing + +Testing plays a large part in complex applications. +A simpler testing strategy is useful when validating that your forms function correctly. +Reactive forms and template-driven forms have different levels of reliance on rendering the UI to perform assertions based on form control and form field changes. +The following examples demonstrate the process of testing forms with reactive and template-driven forms. + +### Testing reactive forms + +Reactive forms provide a relatively straightforward testing strategy because they provide synchronous access to the form and data models, and they can be tested without rendering the UI. +In these tests, status and data are queried and manipulated through the control without interacting with the change detection cycle. + +The following tests use the favorite-color components from previous examples to verify the view-to-model and model-to-view data flows for a reactive form. + + + +#### Verifying view-to-model data flow + +The first example performs the following steps to verify the view-to-model data flow. + +1. Query the view for the form input element, and create a custom "input" event for the test. +1. Set the new value for the input to *Red*, and dispatch the "input" event on the form input element. +1. Assert that the component's `favoriteColorControl` value matches the value from the input. + + + +The next example performs the following steps to verify the model-to-view data flow. + +1. Use the `favoriteColorControl`, a `FormControl` instance, to set the new value. +1. Query the view for the form input element. +1. Assert that the new value set on the control matches the value in the input. + + + +### Testing template-driven forms + +Writing tests with template-driven forms requires a detailed knowledge of the change detection process and an understanding of how directives run on each cycle to ensure that elements are queried, tested, or changed at the correct time. + +The following tests use the favorite color components mentioned earlier to verify the data flows from view to model and model to view for a template-driven form. + +The following test verifies the data flow from view to model. + + + +Here are the steps performed in the view to model test. + +1. Query the view for the form input element, and create a custom "input" event for the test. +1. Set the new value for the input to *Red*, and dispatch the "input" event on the form input element. +1. Run change detection through the test fixture. +1. Assert that the component `favoriteColor` property value matches the value from the input. + +The following test verifies the data flow from model to view. + + + +Here are the steps performed in the model to view test. + +1. Use the component instance to set the value of the `favoriteColor` property. +1. Run change detection through the test fixture. +1. Use the `tick()` method to simulate the passage of time within the `fakeAsync()` task. +1. Query the view for the form input element. +1. Assert that the input value matches the value of the `favoriteColor` property in the component instance. + +## Next steps + +To learn more about reactive forms, see the following guides: + + + + + + + +To learn more about template-driven forms, see the following guides: + + + + + + diff --git a/adev-ja/src/content/guide/forms/overview.md b/adev-ja/src/content/guide/forms/overview.md index 60a3ea327d..f23527f8e6 100644 --- a/adev-ja/src/content/guide/forms/overview.md +++ b/adev-ja/src/content/guide/forms/overview.md @@ -1,111 +1,111 @@ - -Handling user input with forms is the cornerstone of many common applications. + +フォームを使ったユーザー入力の処理は、多くの一般的なアプリケーションの基盤となっています。 -Applications use forms to enable users to log in, to update a profile, to enter sensitive information, and to perform many other data-entry tasks. +アプリケーションは、ユーザーのログインやプロフィールの更新、機密情報を入力したりその他多くのデータ入力タスクを実行できるようにするために、フォームを使用します。 -Angular provides two different approaches to handling user input through forms: reactive and template-driven. -Both capture user input events from the view, validate the user input, create a form model and data model to update, and provide a way to track changes. +Angularは、フォームを通じてユーザー入力を処理するために、リアクティブとテンプレート駆動の2つの異なるアプローチを提供します。 +どちらもビューからのユーザー入力イベントをキャプチャし、ユーザー入力を検証してフォームモデルとデータモデルを作成して更新し、変更を追跡する方法を提供します。 -This guide provides information to help you decide which type of form works best for your situation. -It introduces the common building blocks used by both approaches. -It also summarizes the key differences between the two approaches, and demonstrates those differences in the context of setup, data flow, and testing. +このガイドは、状況に合わせてどちらのタイプのフォームが最適か判断するのに役立つ情報を提供します。 +両方のアプローチで使用される一般的なビルディングブロックを紹介します。 +また、2つのアプローチの主な違いをまとめ、セットアップ、データフロー、テストというコンテキストにおけるそれらの違いを示します。 -## Choosing an approach +## アプローチの選択 {#choosing-an-approach} -Reactive forms and template-driven forms process and manage form data differently. -Each approach offers different advantages. +リアクティブフォームとテンプレート駆動フォームは、フォームデータを処理および管理する方法が異なります。 +それぞれのアプローチは、異なる利点を提供します。 -| Forms | Details | +| フォーム | 詳細 | |:--- |:--- | -| Reactive forms | Provide direct, explicit access to the underlying form's object model. Compared to template-driven forms, they are more robust: they're more scalable, reusable, and testable. If forms are a key part of your application, or you're already using reactive patterns for building your application, use reactive forms. | -| Template-driven forms | Rely on directives in the template to create and manipulate the underlying object model. They are useful for adding a simple form to an app, such as an email list signup form. They're straightforward to add to an app, but they don't scale as well as reactive forms. If you have very basic form requirements and logic that can be managed solely in the template, template-driven forms could be a good fit. | +| リアクティブフォーム | フォームの基礎となるオブジェクトモデルに直接的で明示的なアクセスを提供します。テンプレート駆動フォームと比較して、より堅牢です。スケーラビリティ、再利用性、テスト性が向上します。フォームがアプリケーションの重要な部分である場合、またはアプリケーションの構築にリアクティブパターンをすでに使用している場合は、リアクティブフォームを使用します。 | +| テンプレート駆動フォーム | テンプレート内のディレクティブに依存して、基礎となるオブジェクトモデルを作成および操作します。メールリスト登録フォームなどの、アプリケーションに簡単なフォームを追加するのに役立ちます。アプリケーションへの追加は簡単ですが、リアクティブフォームほどスケーラブルではありません。非常に基本的なフォーム要件と、テンプレートだけで管理できるロジックがある場合は、テンプレート駆動フォームが適している可能性があります。 | -### Key differences +### 主要な違い -The following table summarizes the key differences between reactive and template-driven forms. +次の表は、リアクティブフォームとテンプレート駆動フォームの主な違いをまとめたものです。 -| | Reactive | Template-driven | -|:--- |:--- |:--- | -| [Setup of form model](#setting-up-the-form-model) | Explicit, created in component class | Implicit, created by directives | -| [Data model](#mutability-of-the-data-model) | Structured and immutable | Unstructured and mutable | -| [Data flow](#data-flow-in-forms) | Synchronous | Asynchronous | -| [Form validation](#form-validation) | Functions | Directives | +| | リアクティブ | テンプレート駆動 | +|:--- |:--- |:--- | +| [フォームモデルのセットアップ](#setting-up-the-form-model) | 明示的、コンポーネントクラスで作成 | 黙示的、ディレクティブによって作成 | +| [データモデル](#mutability-of-the-data-model) | 構造化され、不変 | 構造化されていない、可変 | +| [データフロー](#data-flow-in-forms) | 同期 | 非同期 | +| [フォームバリデーション](#form-validation) | 関数 | ディレクティブ | -### Scalability +### スケーラビリティ -If forms are a central part of your application, scalability is very important. -Being able to reuse form models across components is critical. +フォームがアプリケーションの中心的な部分である場合は、スケーラビリティが非常に重要です。 +フォームモデルをコンポーネント間で再利用できることは不可欠です。 -Reactive forms are more scalable than template-driven forms. -They provide direct access to the underlying form API, and use [synchronous data flow](#data-flow-in-reactive-forms) between the view and the data model, which makes creating large-scale forms easier. -Reactive forms require less setup for testing, and testing does not require deep understanding of change detection to properly test form updates and validation. +リアクティブフォームは、テンプレート駆動フォームよりもスケーラブルです。 +フォームの基礎となるAPIに直接アクセスでき、[同期データフロー](#data-flow-in-reactive-forms) をビューとデータモデルの間で使用するため、大規模なフォームの作成が容易になります。 +リアクティブフォームは、テストのためのセットアップが少なく、テストにはフォームの更新とバリデーションを適切にテストするために変更検知の深い理解は必要ありません。 -Template-driven forms focus on simple scenarios and are not as reusable. -They abstract away the underlying form API, and use [asynchronous data flow](#data-flow-in-template-driven-forms) between the view and the data model. -The abstraction of template-driven forms also affects testing. -Tests are deeply reliant on manual change detection execution to run properly, and require more setup. +テンプレート駆動フォームは、単純なシナリオに焦点を当て、再利用性がそれほど高くありません。 +フォームの基礎となるAPIを抽象化し、[非同期データフロー](#data-flow-in-template-driven-forms) をビューとデータモデルの間で使用します。 +テンプレート駆動フォームの抽象化は、テストにも影響を与えます。 +テストは、適切に実行するために手動で変更検知を実行することに大きく依存し、より多くのセットアップが必要です。 -## Setting up the form model +## フォームモデルのセットアップ {#setting-up-the-form-model} -Both reactive and template-driven forms track value changes between the form input elements that users interact with and the form data in your component model. -The two approaches share underlying building blocks, but differ in how you create and manage the common form-control instances. +リアクティブフォームとテンプレート駆動フォームの両方とも、ユーザーが対話するフォーム入力要素と、コンポーネントモデル内のフォームデータの間の値の変更を追跡します。 +2つのアプローチは、基礎となるビルディングブロックを共有しますが、共通のフォームコントロールインスタンスの作成と管理方法が異なります。 -### Common form foundation classes +### 共通のフォーム基盤クラス -Both reactive and template-driven forms are built on the following base classes. +リアクティブフォームとテンプレート駆動フォームの両方は、次のベースクラスに基づいて構築されています。 -| Base classes | Details | +| ベースクラス | 詳細 | |:--- |:--- | -| `FormControl` | Tracks the value and validation status of an individual form control. | -| `FormGroup` | Tracks the same values and status for a collection of form controls. | -| `FormArray` | Tracks the same values and status for an array of form controls. | -| `ControlValueAccessor` | Creates a bridge between Angular `FormControl` instances and built-in DOM elements. | +| `FormControl` | 個々のフォームコントロールの値と検証ステータスを追跡します。 | +| `FormGroup` | フォームコントロールのコレクションの値とステータスを追跡します。 | +| `FormArray` | フォームコントロールの配列の値とステータスを追跡します。 | +| `ControlValueAccessor` | Angular の `FormControl` インスタンスと組み込みの DOM 要素の橋渡しを作成します。 | -### Setup in reactive forms +### リアクティブフォームでのセットアップ -With reactive forms, you define the form model directly in the component class. -The `[formControl]` directive links the explicitly created `FormControl` instance to a specific form element in the view, using an internal value accessor. +リアクティブフォームでは、フォームモデルをコンポーネントクラスに直接定義します。 +`[formControl]` ディレクティブは、明示的に作成された `FormControl` インスタンスを、内部の値アクセサーを使用して、ビュー内の特定のフォーム要素にリンクします。 -The following component implements an input field for a single control, using reactive forms. -In this example, the form model is the `FormControl` instance. +次のコンポーネントは、リアクティブフォームを使用して、単一コントロールの入力フィールドを実装しています。 +この例では、フォームモデルは `FormControl` インスタンスです。 -IMPORTANT: In reactive forms, the form model is the source of truth; it provides the value and status of the form element at any given point in time, through the `[formControl]` directive on the `` element. +IMPORTANT: リアクティブフォームでは、フォームモデルが真実の源です。`` 要素の `[formControl]` ディレクティブを通じて、特定の時点におけるフォーム要素の値とステータスを提供します。 -### Setup in template-driven forms +### テンプレート駆動フォームでのセットアップ -In template-driven forms, the form model is implicit, rather than explicit. -The directive `NgModel` creates and manages a `FormControl` instance for a given form element. +テンプレート駆動フォームにおいてフォームモデルは暗黙的であり、明示的ではありません。 +`NgModel` ディレクティブは、特定のフォーム要素の `FormControl` インスタンスを作成および管理します。 -The following component implements the same input field for a single control, using template-driven forms. +次のコンポーネントは、テンプレート駆動フォームを使用して、単一コントロールの同じ入力フィールドを実装しています。 -IMPORTANT: In a template-driven form the source of truth is the template. The `NgModel` directive automatically manages the `FormControl` instance for you. +IMPORTANT: テンプレート駆動フォームでは、真実の源はテンプレートです。`NgModel` ディレクティブは、`FormControl` インスタンスを自動的に管理します。 -## Data flow in forms +## フォーム内のデータフロー {#data-flow-in-forms} -When an application contains a form, Angular must keep the view in sync with the component model and the component model in sync with the view. -As users change values and make selections through the view, the new values must be reflected in the data model. -Similarly, when the program logic changes values in the data model, those values must be reflected in the view. +アプリケーションにフォームが含まれている場合、Angularはビューをコンポーネントモデルと同期させ、コンポーネントモデルをビューと同期させる必要があります。 +ユーザーがビューを通じて値を変更したり選択したりすると、新しい値はデータモデルに反映される必要があります。 +同様に、プログラムロジックがデータモデルの値を変更すると、これらの値はビューに反映される必要があります。 -Reactive and template-driven forms differ in how they handle data flowing from the user or from programmatic changes. -The following diagrams illustrate both kinds of data flow for each type of form, using the favorite-color input field defined above. +リアクティブフォームとテンプレート駆動フォームは、ユーザーからの変更またはプログラムによる変更からデータが流れる方法が異なります。 +次の図は、上記で定義されたお気に入りの色の入力フィールドを使用して、各タイプのフォームの両方のデータフローを示しています。 -### Data flow in reactive forms +### リアクティブフォームのデータフロー -In reactive forms each form element in the view is directly linked to the form model (a `FormControl` instance). -Updates from the view to the model and from the model to the view are synchronous and do not depend on how the UI is rendered. +リアクティブフォームでは、ビュー内の各フォーム要素は、フォームモデル(`FormControl` インスタンス)に直接リンクされています。 +ビューからモデルへの更新、およびモデルからビューへの更新は同期であり、UIのレンダリング方法に依存しません。 -The view-to-model diagram shows how data flows when an input field's value is changed from the view through the following steps. +ビューからモデルへの図は、入力フィールドの値がビューから変更された場合にデータがどのように流れるかを示しています。 -1. The user types a value into the input element, in this case the favorite color *Blue*. -1. The form input element emits an "input" event with the latest value. -1. The `ControlValueAccessor` listening for events on the form input element immediately relays the new value to the `FormControl` instance. -1. The `FormControl` instance emits the new value through the `valueChanges` observable. -1. Any subscribers to the `valueChanges` observable receive the new value. +1. ユーザーは入力要素にお気に入りの色 *Blue* を入力します。 +1. フォーム入力要素は、最新の値を伴う "input" イベントを発行します。 +1. フォーム入力要素のイベントをリッスンしている `ControlValueAccessor` は、新しい値を `FormControl` インスタンスにすぐに中継します。 +1. `FormControl` インスタンスは、`valueChanges` Observableを通じて新しい値を発行します。 +1. `valueChanges` Observableのサブスクライバーは、新しい値を受け取ります。 ```mermaid flowchart TB @@ -120,12 +120,12 @@ flowchart TB FC-.->|Fires a 'valueChanges' event to observers|O ``` -The model-to-view diagram shows how a programmatic change to the model is propagated to the view through the following steps. +モデルからビューへの図は、モデルに対するプログラムによる変更がどのようにビューに伝播されるかを示しています。 -1. The user calls the `favoriteColorControl.setValue()` method, which updates the `FormControl` value. -1. The `FormControl` instance emits the new value through the `valueChanges` observable. -1. Any subscribers to the `valueChanges` observable receive the new value. -1. The control value accessor on the form input element updates the element with the new value. +1. ユーザーは `favoriteColorControl.setValue()` メソッドを呼び出し、`FormControl` の値を更新します。 +1. `FormControl` インスタンスは、`valueChanges` Observableを通じて新しい値を発行します。 +1. `valueChanges` Observableのサブスクライバーは、新しい値を受け取ります。 +1. フォーム入力要素の制御値アクセサーは、新しい値で要素を更新します。 ```mermaid flowchart TB @@ -140,19 +140,19 @@ flowchart TB CVA-->|"Updates the value of the "|I ``` -### Data flow in template-driven forms +### テンプレート駆動フォームのデータフロー -In template-driven forms, each form element is linked to a directive that manages the form model internally. +テンプレート駆動フォームでは、各フォーム要素は、フォームモデルを内部的に管理するディレクティブにリンクされています。 -The view-to-model diagram shows how data flows when an input field's value is changed from the view through the following steps. +ビューからモデルへの図は、入力フィールドの値がビューから変更された場合にデータがどのように流れるかを示しています。 -1. The user types *Blue* into the input element. -1. The input element emits an "input" event with the value *Blue*. -1. The control value accessor attached to the input triggers the `setValue()` method on the `FormControl` instance. -1. The `FormControl` instance emits the new value through the `valueChanges` observable. -1. Any subscribers to the `valueChanges` observable receive the new value. -1. The control value accessor also calls the `NgModel.viewToModelUpdate()` method which emits an `ngModelChange` event. -1. Because the component template uses two-way data binding for the `favoriteColor` property, the `favoriteColor` property in the component is updated to the value emitted by the `ngModelChange` event \(*Blue*\). +1. ユーザーは入力要素に *Blue* を入力します。 +1. 入力要素は、値 *Blue* を伴う "input" イベントを発行します。 +1. 入力に接続された制御値アクセサーは、`FormControl` インスタンスの `setValue()` メソッドをトリガーします。 +1. `FormControl` インスタンスは、`valueChanges` Observableを通じて新しい値を発行します。 +1. `valueChanges` Observableのサブスクライバーは、新しい値を受け取ります。 +1. 制御値アクセサーは、`ngModelChange` イベントを発行する `NgModel.viewToModelUpdate()` メソッドも呼び出します。 +1. コンポーネントテンプレートが `favoriteColor` プロパティに対して双方向バインディングを使用しているため、コンポーネントの `favoriteColor` プロパティは、`ngModelChange` イベント(*Blue*)によって発行された値に更新されます。 ```mermaid flowchart TB @@ -173,17 +173,17 @@ flowchart TB C-->|Updates the value of the two-way bound property|P ``` -The model-to-view diagram shows how data flows from model to view when the `favoriteColor` changes from *Blue* to *Red*, through the following steps +モデルからビューへの図は、`favoriteColor` が *Blue* から *Red* に変更された場合に、データがモデルからビューにどのように流れるかを示しています。 -1. The `favoriteColor` value is updated in the component. -1. Change detection begins. -1. During change detection, the `ngOnChanges` lifecycle hook is called on the `NgModel` directive instance because the value of one of its inputs has changed. -1. The `ngOnChanges()` method queues an async task to set the value for the internal `FormControl` instance. -1. Change detection completes. -1. On the next tick, the task to set the `FormControl` instance value is executed. -1. The `FormControl` instance emits the latest value through the `valueChanges` observable. -1. Any subscribers to the `valueChanges` observable receive the new value. -1. The control value accessor updates the form input element in the view with the latest `favoriteColor` value. +1. コンポーネントで `favoriteColor` 値が更新されます。 +1. 変更検知が開始されます。 +1. 変更検知中に、`NgModel` ディレクティブインスタンスの入力の1つが変更されたため、`ngOnChanges` ライフサイクルフックが呼び出されます。 +1. `ngOnChanges()` メソッドは、内部 `FormControl` インスタンスの値を設定するための非同期タスクをキューに入れます。 +1. 変更検知が完了します。 +1. 次のティックで、`FormControl` インスタンスの値を設定するタスクが実行されます。 +1. `FormControl` インスタンスは、`valueChanges` Observableを通じて最新の値を発行します。 +1. `valueChanges` Observableのサブスクライバーは、新しい値を受け取ります。 +1. 制御値アクセサーは、ビュー内のフォーム入力要素を、最新の `favoriteColor` 値で更新します。 ```mermaid flowchart TB @@ -214,111 +214,111 @@ flowchart TB end ``` -Note: `NgModel` triggers a second change detection to avoid `ExpressionChangedAfterItHasBeenChecked` errors, because the value change originates in an input binding. +Note: `NgModel` は、値の変更が入力バインディングから発生するため、`ExpressionChangedAfterItHasBeenChecked` エラーを回避するために2回目の変更検知をトリガーします。 -### Mutability of the data model +### データモデルの可変性 {#mutability-of-the-data-model} -The change-tracking method plays a role in the efficiency of your application. +変更追跡の方法は、アプリケーションの効率に影響を与えます。 -| Forms | Details | +| フォーム | 詳細 | |:--- |:--- | -| Reactive forms | Keep the data model pure by providing it as an immutable data structure. Each time a change is triggered on the data model, the `FormControl` instance returns a new data model rather than updating the existing data model. This gives you the ability to track unique changes to the data model through the control's observable. Change detection is more efficient because it only needs to update on unique changes. Because data updates follow reactive patterns, you can integrate with observable operators to transform data. | -| Template-driven forms | Rely on mutability with two-way data binding to update the data model in the component as changes are made in the template. Because there are no unique changes to track on the data model when using two-way data binding, change detection is less efficient at determining when updates are required. | +| リアクティブフォーム | データモデルを、不変のデータ構造として提供することで、データモデルを純粋に保ちます。データモデルで変更がトリガーされるたびに、`FormControl` インスタンスは、既存のデータモデルを更新するのではなく、新しいデータモデルを返します。これにより、コントロールのObservableを通じて、データモデルに対する一意の変更を追跡できます。変更検知は、一意の変更でのみ更新する必要があるため、より効率的です。データの更新はリアクティブパターンに従うため、Observableオペレーターと統合してデータを変更できます。 | +| テンプレート駆動フォーム | テンプレートでの変更が行われると、コンポーネント内のデータモデルを更新するために、双方向バインディングを使用して可変性を活用します。双方向バインディングを使用する場合は、データモデルに対する一意の変更を追跡できないため、変更検知は、更新が必要なときに判断する効率が低くなります。 | -The difference is demonstrated in the previous examples that use the favorite-color input element. +この違いは、お気に入りの色の入力要素を使用する前の例で示されています。 -* With reactive forms, the **`FormControl` instance** always returns a new value when the control's value is updated -* With template-driven forms, the **favorite color property** is always modified to its new value +* リアクティブフォームの場合、**`FormControl` インスタンス** は、コントロールの値が更新されると常に新しい値を返します +* テンプレート駆動フォームの場合、**お気に入りの色のプロパティ** は、常にその新しい値に変更されます -## Form validation +## フォームバリデーション {#form-validation} -Validation is an integral part of managing any set of forms. -Whether you're checking for required fields or querying an external API for an existing username, Angular provides a set of built-in validators as well as the ability to create custom validators. +バリデーションは、フォームのセットを管理する上で不可欠な部分です。 +必須フィールドを確認しているか、外部APIに既存のユーザー名を確認しているかにかかわらず、Angularは一連の組み込みバリデーターと、カスタムバリデーターを作成する機能を提供します。 -| Forms | Details | +| フォーム | 詳細 | |:--- |:--- | -| Reactive forms | Define custom validators as **functions** that receive a control to validate | -| Template-driven forms | Tied to template **directives**, and must provide custom validator directives that wrap validation functions | +| リアクティブフォーム | バリデートするコントロールを受け取る**関数**として、カスタムバリデーターを定義します | +| テンプレート駆動フォーム | テンプレート**ディレクティブ**に結び付けられ、バリデーション関数をラップするカスタムバリデーターディレクティブを提供する必要があります | -For more information, see [Form Validation](guide/forms/form-validation#validating-input-in-reactive-forms). +詳細については、[フォームバリデーション](guide/forms/form-validation#validating-input-in-reactive-forms) を参照してください。 -## Testing +## テスト -Testing plays a large part in complex applications. -A simpler testing strategy is useful when validating that your forms function correctly. -Reactive forms and template-driven forms have different levels of reliance on rendering the UI to perform assertions based on form control and form field changes. -The following examples demonstrate the process of testing forms with reactive and template-driven forms. +テストは、複雑なアプリケーションで重要な役割を果たします。 +フォームが正しく機能することを検証する際に、より簡単なテスト戦略が役立ちます。 +リアクティブフォームとテンプレート駆動フォームは、UIをレンダリングすることに対して異なるレベルの依存関係があり、フォームコントロールとフォームフィールドの変更に基づいてアサーションを実行します。 +次の例は、リアクティブフォームとテンプレート駆動フォームを使用してフォームをテストするプロセスを示しています。 -### Testing reactive forms +### リアクティブフォームのテスト -Reactive forms provide a relatively straightforward testing strategy because they provide synchronous access to the form and data models, and they can be tested without rendering the UI. -In these tests, status and data are queried and manipulated through the control without interacting with the change detection cycle. +リアクティブフォームは、フォームとデータモデルに同期的にアクセスできるため、比較的簡単なテスト戦略を提供し、UIをレンダリングせずにテストできます。 +これらのテストでは、ステータスとデータは、変更検知サイクルと対話せずに、コントロールを通じてクエリおよび操作されます。 -The following tests use the favorite-color components from previous examples to verify the view-to-model and model-to-view data flows for a reactive form. +次のテストは、前の例にあるお気に入りの色のコンポーネントを使用して、リアクティブフォームのビューからモデルへのデータフロー、およびモデルからビューへのデータフローを確認します。 -#### Verifying view-to-model data flow +#### ビューからモデルへのデータフローを確認する -The first example performs the following steps to verify the view-to-model data flow. +最初の例は、ビューからモデルへのデータフローを確認するために、次の手順を実行します。 -1. Query the view for the form input element, and create a custom "input" event for the test. -1. Set the new value for the input to *Red*, and dispatch the "input" event on the form input element. -1. Assert that the component's `favoriteColorControl` value matches the value from the input. +1. ビューからフォーム入力要素をクエリし、テスト用のカスタム "input" イベントを作成します。 +1. 入力の新しい値を *Red* に設定し、フォーム入力要素で "input" イベントをディスパッチします。 +1. コンポーネントの `favoriteColorControl` 値が入力からの値と一致することをアサートします。 - + -The next example performs the following steps to verify the model-to-view data flow. +次の例は、モデルからビューへのデータフローを確認するために、次の手順を実行します。 -1. Use the `favoriteColorControl`, a `FormControl` instance, to set the new value. -1. Query the view for the form input element. -1. Assert that the new value set on the control matches the value in the input. +1. `favoriteColorControl`(`FormControl` インスタンス)を使用して、新しい値を設定します。 +1. ビューからフォーム入力要素をクエリします。 +1. コントロールに設定された新しい値が入力内の値と一致することをアサートします。 - + -### Testing template-driven forms +### テンプレート駆動フォームのテスト -Writing tests with template-driven forms requires a detailed knowledge of the change detection process and an understanding of how directives run on each cycle to ensure that elements are queried, tested, or changed at the correct time. +テンプレート駆動フォームでテストを作成するには、変更検知プロセスの詳細な知識と、各サイクルでディレクティブがどのように実行されるかを理解する必要があり、要素が適切なタイミングでクエリ、テスト、変更されることを保証します。 -The following tests use the favorite color components mentioned earlier to verify the data flows from view to model and model to view for a template-driven form. +次のテストは、先に述べたお気に入りの色のコンポーネントを使用して、テンプレート駆動フォームのビューからモデルへのデータフロー、およびモデルからビューへのデータフローを確認します。 -The following test verifies the data flow from view to model. +次のテストは、ビューからモデルへのデータフローを確認します。 - + -Here are the steps performed in the view to model test. +ビューからモデルへのテストで実行される手順を以下に示します。 -1. Query the view for the form input element, and create a custom "input" event for the test. -1. Set the new value for the input to *Red*, and dispatch the "input" event on the form input element. -1. Run change detection through the test fixture. -1. Assert that the component `favoriteColor` property value matches the value from the input. +1. ビューからフォーム入力要素をクエリし、テスト用のカスタム "input" イベントを作成します。 +1. 入力の新しい値を *Red* に設定し、フォーム入力要素で "input" イベントをディスパッチします。 +1. テストフィクスチャを通じて変更検知を実行します。 +1. コンポーネントの `favoriteColor` プロパティ値が入力からの値と一致することをアサートします。 -The following test verifies the data flow from model to view. +次のテストは、モデルからビューへのデータフローを確認します。 - + -Here are the steps performed in the model to view test. +モデルからビューへのテストで実行される手順を以下に示します。 -1. Use the component instance to set the value of the `favoriteColor` property. -1. Run change detection through the test fixture. -1. Use the `tick()` method to simulate the passage of time within the `fakeAsync()` task. -1. Query the view for the form input element. -1. Assert that the input value matches the value of the `favoriteColor` property in the component instance. +1. コンポーネントインスタンスを使用して、`favoriteColor` プロパティの値を設定します。 +1. テストフィクスチャを通じて変更検知を実行します。 +1. `fakeAsync()` タスク内で、`tick()` メソッドを使用して時間の経過をシミュレートします。 +1. ビューからフォーム入力要素をクエリします。 +1. 入力の値が、コンポーネントインスタンスの `favoriteColor` プロパティの値と一致することをアサートします。 -## Next steps +## 次のステップ -To learn more about reactive forms, see the following guides: +リアクティブフォームの詳細については、次のガイドを参照してください。 - - - + + + -To learn more about template-driven forms, see the following guides: +テンプレート駆動フォームの詳細については、次のガイドを参照してください。 - - - + + + diff --git a/adev-ja/src/content/guide/forms/reactive-forms.en.md b/adev-ja/src/content/guide/forms/reactive-forms.en.md new file mode 100644 index 0000000000..dd830ffe3b --- /dev/null +++ b/adev-ja/src/content/guide/forms/reactive-forms.en.md @@ -0,0 +1,419 @@ +# Reactive forms + +Reactive forms provide a model-driven approach to handling form inputs whose values change over time. +This guide shows you how to create and update a basic form control, progress to using multiple controls in a group, validate form values, and create dynamic forms where you can add or remove controls at run time. + +## Overview of reactive forms + +Reactive forms use an explicit and immutable approach to managing the state of a form at a given point in time. +Each change to the form state returns a new state, which maintains the integrity of the model between changes. +Reactive forms are built around observable streams, where form inputs and values are provided as streams of input values, which can be accessed synchronously. + +Reactive forms also provide a straightforward path to testing because you are assured that your data is consistent and predictable when requested. +Any consumers of the streams have access to manipulate that data safely. + +Reactive forms differ from [template-driven forms](guide/forms/template-driven-forms) in distinct ways. +Reactive forms provide synchronous access to the data model, immutability with observable operators, and change tracking through observable streams. + +Template-driven forms let direct access modify data in your template, but are less explicit than reactive forms because they rely on directives embedded in the template, along with mutable data to track changes asynchronously. +See the [Forms Overview](guide/forms) for detailed comparisons between the two paradigms. + +## Adding a basic form control + +There are three steps to using form controls. + +1. Register the reactive forms module in your application. + This module declares the reactive-form directives that you need to use reactive forms. + +1. Generate a new component and instantiate a new `FormControl`. +1. Register the `FormControl` in the template. + +You can then display the form by adding the component to the template. + +The following examples show how to add a single form control. +In the example, the user enters their name into an input field, captures that input value, and displays the current value of the form control element. + + + + +To use reactive form controls, import `ReactiveFormsModule` from the `@angular/forms` package and add it to your NgModule's `imports` array. + + + + + +Use the CLI command `ng generate component` to generate a component in your project to host the control. + + + +Use the constructor of `FormControl` to set its initial value, which in this case is an empty string. By creating these controls in your component class, you get immediate access to listen for, update, and validate the state of the form input. + + + +After you create the control in the component class, you must associate it with a form control element in the template. Update the template with the form control using the `formControl` binding provided by `FormControlDirective`, which is also included in the `ReactiveFormsModule`. + + + +Using the template binding syntax, the form control is now registered to the `name` input element in the template. The form control and DOM element communicate with each other: the view reflects changes in the model, and the model reflects changes in the view. + + + +The `FormControl` assigned to the `name` property is displayed when the `` component is added to a template. + + + + + +### Displaying a form control value + +You can display the value in the following ways. + +* Through the `valueChanges` observable where you can listen for changes in the form's value in the template using `AsyncPipe` or in the component class using the `subscribe()` method +* With the `value` property, which gives you a snapshot of the current value + +The following example shows you how to display the current value using interpolation in the template. + + + +The displayed value changes as you update the form control element. + +Reactive forms provide access to information about a given control through properties and methods provided with each instance. +These properties and methods of the underlying [AbstractControl](api/forms/AbstractControl "API reference") class are used to control form state and determine when to display messages when handling [input validation](#validating-form-input "Learn more about validating form input"). + +Read about other `FormControl` properties and methods in the [API Reference](api/forms/FormControl "Detailed syntax reference"). + +### Replacing a form control value + +Reactive forms have methods to change a control's value programmatically, which gives you the flexibility to update the value without user interaction. +A form control instance provides a `setValue()` method that updates the value of the form control and validates the structure of the value provided against the control's structure. +For example, when retrieving form data from a backend API or service, use the `setValue()` method to update the control to its new value, replacing the old value entirely. + +The following example adds a method to the component class to update the value of the control to *Nancy* using the `setValue()` method. + + + +Update the template with a button to simulate a name update. +When you click the **Update Name** button, the value entered in the form control element is reflected as its current value. + + + +The form model is the source of truth for the control, so when you click the button, the value of the input is changed within the component class, overriding its current value. + +HELPFUL: In this example, you're using a single control. +When using the `setValue()` method with a [form group](#grouping-form-controls) or [form array](#creating-dynamic-forms) instance, the value needs to match the structure of the group or array. + +## Grouping form controls + +Forms typically contain several related controls. +Reactive forms provide two ways of grouping multiple related controls into a single input form. + +| Form groups | Details | +|:--- |:--- | +| Form group | Defines a form with a fixed set of controls that you can manage together. Form group basics are discussed in this section. You can also [nest form groups](#creating-nested-form-groups "See more about nesting groups") to create more complex forms. | +| Form array | Defines a dynamic form, where you can add and remove controls at run time. You can also nest form arrays to create more complex forms. For more about this option, see [Creating dynamic forms](#creating-dynamic-forms). | + +Just as a form control instance gives you control over a single input field, a form group instance tracks the form state of a group of form control instances \(for example, a form\). +Each control in a form group instance is tracked by name when creating the form group. +The following example shows how to manage multiple form control instances in a single group. + +Generate a `ProfileEditor` component and import the `FormGroup` and `FormControl` classes from the `@angular/forms` package. + + +ng generate component ProfileEditor + + + + +To add a form group to this component, take the following steps. + +1. Create a `FormGroup` instance. +1. Associate the `FormGroup` model and view. +1. Save the form data. + + + + +Create a property in the component class named `profileForm` and set the property to a new form group instance. To initialize the form group, provide the constructor with an object of named keys mapped to their control. + +For the profile form, add two form control instances with the names `firstName` and `lastName` + + + +The individual form controls are now collected within a group. A `FormGroup` instance provides its model value as an object reduced from the values of each control in the group. A form group instance has the same properties (such as `value` and `untouched`) and methods (such as `setValue()`) as a form control instance. + + + +A form group tracks the status and changes for each of its controls, so if one of the controls changes, the parent control also emits a new status or value change. The model for the group is maintained from its members. After you define the model, you must update the template to reflect the model in the view. + + + +Just as a form group contains a group of controls, the *profileForm* `FormGroup` is bound to the `form` element with the `FormGroup` directive, creating a communication layer between the model and the form containing the inputs. The `formControlName` input provided by the `FormControlName` directive binds each individual input to the form control defined in `FormGroup`. The form controls communicate with their respective elements. They also communicate changes to the form group instance, which provides the source of truth for the model value. + + + +The `ProfileEditor` component accepts input from the user, but in a real scenario you want to capture the form value and make it available for further processing outside the component. The `FormGroup` directive listens for the `submit` event emitted by the `form` element and emits an `ngSubmit` event that you can bind to a callback function. Add an `ngSubmit` event listener to the `form` tag with the `onSubmit()` callback method. + + + +The `onSubmit()` method in the `ProfileEditor` component captures the current value of `profileForm`. Use `EventEmitter` to keep the form encapsulated and to provide the form value outside the component. The following example uses `console.warn` to log a message to the browser console. + + + +The `submit` event is emitted by the `form` tag using the built-in DOM event. You trigger the event by clicking a button with `submit` type. This lets the user press the **Enter** key to submit the completed form. + +Use a `button` element to add a button to the bottom of the form to trigger the form submission. + + + +The button in the preceding snippet also has a `disabled` binding attached to it to disable the button when `profileForm` is invalid. You aren't performing any validation yet, so the button is always enabled. Basic form validation is covered in the [Validating form input](#validating-form-input) section. + + + +To display the `ProfileEditor` component that contains the form, add it to a component template. + + + +`ProfileEditor` lets you manage the form control instances for the `firstName` and `lastName` controls within the form group instance. + +### Creating nested form groups + +Form groups can accept both individual form control instances and other form group instances as children. +This makes composing complex form models easier to maintain and logically group together. + +When building complex forms, managing the different areas of information is easier in smaller sections. +Using a nested form group instance lets you break large forms groups into smaller, more manageable ones. + +To make more complex forms, use the following steps. + +1. Create a nested group. +1. Group the nested form in the template. + +Some types of information naturally fall into the same group. +A name and address are typical examples of such nested groups, and are used in the following examples. + + + +To create a nested group in `profileForm`, add a nested `address` element to the form group instance. + + + +In this example, `address group` combines the current `firstName` and `lastName` controls with the new `street`, `city`, `state`, and `zip` controls. Even though the `address` element in the form group is a child of the overall `profileForm` element in the form group, the same rules apply with value and status changes. Changes in status and value from the nested form group propagate to the parent form group, maintaining consistency with the overall model. + + + +After you update the model in the component class, update the template to connect the form group instance and its input elements. Add the `address` form group containing the `street`, `city`, `state`, and `zip` fields to the `ProfileEditor` template. + + + +The `ProfileEditor` form is displayed as one group, but the model is broken down further to represent the logical grouping areas. + +Display the value for the form group instance in the component template using the `value` property and `JsonPipe`. + + + +### Updating parts of the data model + +When updating the value for a form group instance that contains multiple controls, you might only want to update parts of the model. +This section covers how to update specific parts of a form control data model. + +There are two ways to update the model value: + +| Methods | Details | +|:--- |:--- | +| `setValue()` | Set a new value for an individual control. The `setValue()` method strictly adheres to the structure of the form group and replaces the entire value for the control. | +| `patchValue()` | Replace any properties defined in the object that have changed in the form model. | + +The strict checks of the `setValue()` method help catch nesting errors in complex forms, while `patchValue()` fails silently on those errors. + +In `ProfileEditorComponent`, use the `updateProfile` method with the following example to update the first name and street address for the user. + + + +Simulate an update by adding a button to the template to update the user profile on demand. + + + +When a user clicks the button, the `profileForm` model is updated with new values for `firstName` and `street`. Notice that `street` is provided in an object inside the `address` property. +This is necessary because the `patchValue()` method applies the update against the model structure. +`PatchValue()` only updates properties that the form model defines. + +## Using the FormBuilder service to generate controls + +Creating form control instances manually can become repetitive when dealing with multiple forms. +The `FormBuilder` service provides convenient methods for generating controls. + +Use the following steps to take advantage of this service. + +1. Import the `FormBuilder` class. +1. Inject the `FormBuilder` service. +1. Generate the form contents. + +The following examples show how to refactor the `ProfileEditor` component to use the form builder service to create form control and form group instances. + + + +Import the `FormBuilder` class from the `@angular/forms` package. + + + + + + +The `FormBuilder` service is an injectable provider that is provided with the reactive forms module. Inject this dependency by adding it to the component constructor. + + + + + +The `FormBuilder` service has three methods: `control()`, `group()`, and `array()`. These are factory methods for generating instances in your component classes including form controls, form groups, and form arrays. Use the `group` method to create the `profileForm` controls. + + + +In the preceding example, you use the `group()` method with the same object to define the properties in the model. The value for each control name is an array containing the initial value as the first item in the array. + +Tip: You can define the control with just the initial value, but if your controls need sync or async validation, add sync and async validators as the second and third items in the array. Compare using the form builder to creating the instances manually. + + + + + + + + + +## Validating form input + +*Form validation* is used to ensure that user input is complete and correct. +This section covers adding a single validator to a form control and displaying the overall form status. +Form validation is covered more extensively in the [Form Validation](guide/forms/form-validation) guide. + +Use the following steps to add form validation. + +1. Import a validator function in your form component. +1. Add the validator to the field in the form. +1. Add logic to handle the validation status. + +The most common validation is making a field required. +The following example shows how to add a required validation to the `firstName` control and display the result of validation. + + + +Reactive forms include a set of validator functions for common use cases. These functions receive a control to validate against and return an error object or a null value based on the validation check. + +Import the `Validators` class from the `@angular/forms` package. + + + + + +In the `ProfileEditor` component, add the `Validators.required` static method as the second item in the array for the `firstName` control. + + + + + +When you add a required field to the form control, its initial status is invalid. This invalid status propagates to the parent form group element, making its status invalid. Access the current status of the form group instance through its `status` property. + +Display the current status of `profileForm` using interpolation. + + + +The **Submit** button is disabled because `profileForm` is invalid due to the required `firstName` form control. After you fill out the `firstName` input, the form becomes valid and the **Submit** button is enabled. + +For more on form validation, visit the [Form Validation](guide/forms/form-validation) guide. + + + +## Creating dynamic forms + +`FormArray` is an alternative to `FormGroup` for managing any number of unnamed controls. +As with form group instances, you can dynamically insert and remove controls from form array instances, and the form array instance value and validation status is calculated from its child controls. +However, you don't need to define a key for each control by name, so this is a great option if you don't know the number of child values in advance. + +To define a dynamic form, take the following steps. + +1. Import the `FormArray` class. +1. Define a `FormArray` control. +1. Access the `FormArray` control with a getter method. +1. Display the form array in a template. + +The following example shows you how to manage an array of *aliases* in `ProfileEditor`. + + + +Import the `FormArray` class from `@angular/forms` to use for type information. The `FormBuilder` service is ready to create a `FormArray` instance. + + + + + +You can initialize a form array with any number of controls, from zero to many, by defining them in an array. Add an `aliases` property to the form group instance for `profileForm` to define the form array. + +Use the `FormBuilder.array()` method to define the array, and the `FormBuilder.control()` method to populate the array with an initial control. + + + +The aliases control in the form group instance is now populated with a single control until more controls are added dynamically. + + + +A getter provides access to the aliases in the form array instance compared to repeating the `profileForm.get()` method to get each instance. The form array instance represents an undefined number of controls in an array. It's convenient to access a control through a getter, and this approach is straightforward to repeat for additional controls.
+ +Use the getter syntax to create an `aliases` class property to retrieve the alias's form array control from the parent form group. + + + +Because the returned control is of the type `AbstractControl`, you need to provide an explicit type to access the method syntax for the form array instance. Define a method to dynamically insert an alias control into the alias's form array. The `FormArray.push()` method inserts the control as a new item in the array. + + + +In the template, each control is displayed as a separate input field. + +
+ + + +To attach the aliases from your form model, you must add it to the template. Similar to the `formGroupName` input provided by `FormGroupNameDirective`, `formArrayName` binds communication from the form array instance to the template with `FormArrayNameDirective`. + +Add the following template HTML after the `
` closing the `formGroupName` element. + + + +The `*ngFor` directive iterates over each form control instance provided by the aliases form array instance. Because form array elements are unnamed, you assign the index to the `i` variable and pass it to each control to bind it to the `formControlName` input. + +Each time a new alias instance is added, the new form array instance is provided its control based on the index. This lets you track each individual control when calculating the status and value of the root control. + + + + + +Initially, the form contains one `Alias` field. To add another field, click the **Add Alias** button. You can also validate the array of aliases reported by the form model displayed by `Form Value` at the bottom of the template. Instead of a form control instance for each alias, you can compose another form group instance with additional fields. The process of defining a control for each item is the same. + + + + +## Reactive forms API summary + +The following table lists the base classes and services used to create and manage reactive form controls. +For complete syntax details, see the API reference documentation for the [Forms package](api#forms "API reference"). + +### Classes + +| Class | Details | +|:--- |:--- | +| `AbstractControl` | The abstract base class for the concrete form control classes `FormControl`, `FormGroup`, and `FormArray`. It provides their common behaviors and properties. | +| `FormControl` | Manages the value and validity status of an individual form control. It corresponds to an HTML form control such as `` or `` or `` や `` control element has the HTML5 `required` attribute + * The **Studio** `` control element does not because `studio` is optional + + The **Submit** button has some classes on it for styling. + At this point, the form layout is all plain HTML5, with no bindings or directives. + +1. The sample form uses some style classes from [Twitter Bootstrap](https://getbootstrap.com/css): `container`, `form-group`, `form-control`, and `btn`. + To use these styles, the application's style sheet imports the library. + + + +1. The form requires that an actor's skill is chosen from a predefined list of `skills` maintained internally in `ActorFormComponent`. + The Angular [NgForOf directive](api/common/NgForOf "API reference") iterates over the data values to populate the `` tag next to the **Name** label. +1. Add the `ngModel` directive, using two-way data binding syntax `[(ngModel)]="..."`. + + + +HELPFUL: This example has a temporary diagnostic interpolation after each input tag, `{{model.name}}`, to show the current data value of the corresponding property. The comment reminds you to remove the diagnostic lines when you have finished observing the two-way data binding at work. + +### Access the overall form status + +When you imported the `FormsModule` in your component, Angular automatically created and attached an [NgForm](api/forms/NgForm) directive to the `` tag in the template (because `NgForm` has the selector `form` that matches `` elements). + +To get access to the `NgForm` and the overall form status, declare a [template reference variable](guide/templates/reference-variables). + +1. Edit the template file `actor-form.component.html`. +1. Update the `` tag with a template reference variable, `#actorForm`, and set its value as follows. + + + + The `actorForm` template variable is now a reference to the `NgForm` directive instance that governs the form as a whole. + +1. Run the app. +1. Start typing in the **Name** input box. + + As you add and delete characters, you can see them appear and disappear from the data model. + + The diagnostic line that shows interpolated values demonstrates that values are really flowing from the input box to the model and back again. + +### Naming control elements + +When you use `[(ngModel)]` on an element, you must define a `name` attribute for that element. +Angular uses the assigned name to register the element with the `NgForm` directive attached to the parent `` element. + +The example added a `name` attribute to the `` element and set it to "name", which makes sense for the actor's name. +Any unique value will do, but using a descriptive name is helpful. + +1. Add similar `[(ngModel)]` bindings and `name` attributes to **Studio** and **Skill**. +1. You can now remove the diagnostic messages that show interpolated values. +1. To confirm that two-way data binding works for the entire actor model, add a new text binding with the [`json`](api/common/JsonPipe) pipe at the top to the component's template, which serializes the data to a string. + +After these revisions, the form template should look like the following: + + + +You'll notice that: + +* Each `` element has an `id` property. + This is used by the `