詳細ガイド
フォーム

バリデーション

フォームには、ユーザーが送信前に正しく完全なデータを提供することを保証するためにバリデーションが必要です。バリデーションがない場合、サーバー側でデータ品質の問題を処理し、不明瞭なエラーメッセージでユーザー体験を低下させ、すべての制約を手動でチェックする必要があるでしょう。

シグナルフォームは、スキーマベースのバリデーションアプローチを提供します。バリデーションルールはスキーマ関数を使用してフィールドにバインドされ、値が変更されると自動的に実行され、フィールド状態シグナルを通じてエラーを公開します。これにより、ユーザーがフォームを操作するにつれて更新されるリアクティブなバリデーションが可能になります。

バリデーションの基本

シグナルフォームにおけるバリデーションは、form()の第二引数として渡されるスキーマ関数を通じて定義されます。

スキーマ関数

スキーマ関数は、バリデーションルールを定義するためのSchemaPathTreeオブジェクトを受け取ります:

app.ts

/**
 * @license
 * Copyright Google LLC All Rights Reserved.
 *
 * Use of this source code is governed by an MIT-style license that can be
 * found in the LICENSE file at https://angular.dev/license
 */

import {Component, signal} from '@angular/core';
import {email, form, FormField, required, submit} from '@angular/forms/signals';

interface LoginData {
  email: string;
  password: string;
}

@Component({
  selector: 'app-root',
  templateUrl: 'app.html',
  styleUrl: 'app.css',
  imports: [FormField],
})
export class App {
  loginModel = signal<LoginData>({
    email: '',
    password: '',
  });

  loginForm = form(this.loginModel, (schemaPath) => {
    required(schemaPath.email, {message: 'Email is required'});
    email(schemaPath.email, {message: 'Enter a valid email address'});

    required(schemaPath.password, {message: 'Password is required'});
  });

  onSubmit(event: Event) {
    event.preventDefault();
    submit(this.loginForm, {
      action: async () => {
        const credentials = this.loginModel();
        // In a real app, this would be async:
        // await this.authService.login(credentials);
        console.log('Logging in with:', credentials);
      },
    });
  }
}

スキーマ関数はフォームの初期化中に一度だけ実行されます。バリデーションルールはスキーマパスパラメータ(schemaPath.emailやschemaPath.passwordなど)を使用してフィールドにバインドされ、フィールドの値が変更されるたびにバリデーションが自動的に実行されます。

NOTE: スキーマのコールバックパラメータ(この例ではschemaPath)は、フォーム内のすべてのフィールドへのパスを提供するSchemaPathTreeオブジェクトです。このパラメータには好きな名前を付けることができます。

バリデーションの仕組み

シグナルフォームのバリデーションは、次のパターンに従います:

  1. スキーマでバリデーションルールを定義 - スキーマ関数内でバリデーションルールをフィールドにバインドします
  2. 自動実行 - フィールドの値が変更されるとバリデーションルールが実行されます
  3. エラーの伝播 - バリデーションエラーはフィールドの状態シグナルを通じて公開されます
  4. リアクティブな更新 - バリデーションの状態が変化するとUIが自動的に更新されます

インタラクティブなフィールドでは、値が変更されるたびにバリデーションが実行されます。非表示および無効化されたフィールドではバリデーションは実行されません - それらのバリデーションルールは、フィールドが再びインタラクティブになるまでスキップされます。

バリデーションのタイミング

バリデーションルールは次の順序で実行されます:

  1. 同期バリデーション - 値が変更されると、すべての同期バリデーションルールが実行されます
  2. 非同期バリデーション - 非同期バリデーションルールは、すべての同期バリデーションルールが成功した後にのみ実行されます
  3. フィールドの状態更新 - valid()、invalid()、errors()、pending()シグナルが更新されます

同期バリデーションルール(required()やemail()など)は即座に完了します。非同期バリデーションルール(validateHttp()など)は時間がかかる場合があり、実行中はpending()シグナルをtrueに設定します。

すべてのバリデーションルールは変更のたびに実行されます - バリデーションは最初のエラーで中断されません。フィールドにrequired()とemail()の両方のバリデーションルールがある場合、両方が実行され、両方が同時にエラーを生成する可能性があります。

ネイティブHTMLバリデーション

シグナルフォームは、バリデーションルールの実行にブラウザ組み込みの制約バリデーションを使用しません。これは意図的な設計です。シグナルフォームは、ネイティブのフォーム要素だけでなく、任意のコンポーネントをフォームコントロールとして扱えるようにするためです。

代わりに、バリデーションルールはすべてAngular内で実行され、バリデーションの状態は要素のネイティブなvalidity状態ではなく、valid()、invalid()、errors()などのフィールド状態シグナルを通じて公開されます。FormRootディレクティブは、フォーム要素にnovalidate属性も設定するため、ブラウザが送信をブロックすることはありません。

フィールドがネイティブのフォーム要素にバインドされている場合、一部の組み込みバリデーションルールは、その制約を対応するネイティブ属性にミラーリングします。required()、min()、max()、minLength()、maxLength()は、要素がサポートしていればrequired、min、max、minlength、maxlength属性を設定します。例外はpattern()で、これはネイティブのpattern属性を設定しません。シグナルフォームがこれらの属性を設定するのは、入力の挙動を制御し、アクセシビリティを向上させるためであり、ネイティブのバリデーションをトリガーするためではありません。

NOTE: シグナルフォームがネイティブのvalidity状態を読み取るケースが1つだけあります。ブラウザがネイティブの入力値をパースできない場合(たとえば、日付の途中入力など)、シグナルフォームはそれをパースエラーとして報告します。この場合も、エラーは他のバリデーションエラーと同様にフィールドのerrors()シグナルを通じて公開されます。詳細は値の変換を参照してください。

IMPORTANT: :validや:invalidのCSS疑似クラス、要素のvalidityプロパティ、validationMessageといったネイティブのvalidity機能に依存しないでください。ミラーリングされた属性の副作用として、ブラウザが一部の入力を無効と報告することがあります(たとえば、minを下回る値を持つnumber入力など)が、この挙動はバリデーションルールと入力タイプによって異なり、バリデーション状態を観測するためにサポートされた方法ではありません。

バリデーション状態に基づいてコントロールをスタイリングするには、フィールド状態シグナルにクラスをバインドする(フィールド状態管理を参照)か、自動ステータスクラスを設定してください(自動ステータスクラスを参照)。

組み込みのバリデーションルール

シグナルフォームは、一般的なバリデーションシナリオのためのバリデーションルールを提供します。すべての組み込みバリデーションルールは、カスタムエラーメッセージと条件付きロジックのためのオプションオブジェクトを受け入れます。

required()

required()バリデーションルールは、フィールドに値があることを保証します:

import {Component, signal} from '@angular/core';
import {form, FormField, required} from '@angular/forms/signals';

@Component({
  selector: 'app-registration',
  imports: [FormField],
  template: `
    <form novalidate>
      <label>
        Username
        <input [formField]="registrationForm.username" />
      </label>

      <label>
        Email
        <input type="email" [formField]="registrationForm.email" />
      </label>

      <button type="submit">Register</button>
    </form>
  `,
})
export class RegistrationComponent {
  registrationModel = signal({
    username: '',
    email: '',
  });

  registrationForm = form(this.registrationModel, (schemaPath) => {
    required(schemaPath.username, {message: 'Username is required'});
    required(schemaPath.email, {message: 'Email is required'});
  });
}

A field is considered "empty" when its value is one of the following, and non-empty for every other value — including 0 and the empty array []:

Condition Example
Value is null null
Value is undefined undefined
Value is an empty string ''
Value is false false
Value is NaN NaN

The last two are worth calling out:

  • false is empty to follow the native semantics of required on <input type="checkbox">, where an unchecked box fails validation.
  • NaN is empty because it is usually the result of a parsing error, and is not a valid number.

条件付きの要件には、whenオプションを使用します:

registrationForm = form(this.registrationModel, (schemaPath) => {
  required(schemaPath.promoCode, {
    message: 'Promo code is required for discounts',
    when: ({valueOf}) => valueOf(schemaPath.applyDiscount),
  });
});

バリデーションルールは、when関数がtrueを返す場合にのみ実行されます。

NOTE: requiredは空の配列を「存在する(有効)」として扱うため、配列の最小要素数を強制するにはminLength()を使用してください。

email()

email()バリデーションルールは、有効なメール形式をチェックします:

import {Component, signal} from '@angular/core';
import {form, FormField, email} from '@angular/forms/signals';

@Component({
  selector: 'app-contact',
  imports: [FormField],
  template: `
    <form novalidate>
      <label>
        Your Email
        <input type="email" [formField]="contactForm.email" />
      </label>
    </form>
  `,
})
export class ContactComponent {
  contactModel = signal({email: ''});

  contactForm = form(this.contactModel, (schemaPath) => {
    email(schemaPath.email, {message: 'Please enter a valid email address'});
  });
}

email()バリデーションルールは、標準的なメール形式の正規表現を使用します。user@example.comのようなアドレスは受け入れますが、user@や@example.comのような不正な形式のアドレスは拒否します。

min()とmax()

min()とmax()バリデーションルールは、数値に対して機能します:

import {Component, signal} from '@angular/core';
import {form, FormField, min, max} from '@angular/forms/signals';

@Component({
  selector: 'app-age-form',
  imports: [FormField],
  template: `
    <form novalidate>
      <label>
        Age
        <input type="number" [formField]="ageForm.age" />
      </label>

      <label>
        Rating (1-5)
        <input type="number" [formField]="ageForm.rating" />
      </label>
    </form>
  `,
})
export class AgeFormComponent {
  ageModel = signal({
    age: 0,
    rating: 0,
  });

  ageForm = form(this.ageModel, (schemaPath) => {
    min(schemaPath.age, 18, {message: 'You must be at least 18 years old'});
    max(schemaPath.age, 120, {message: 'Please enter a valid age'});

    min(schemaPath.rating, 1, {message: 'Rating must be at least 1'});
    max(schemaPath.rating, 5, {message: 'Rating cannot exceed 5'});
  });
}

動的な制約のために、算出値を使用できます:

ageForm = form(this.ageModel, (schemaPath) => {
  min(schemaPath.participants, () => this.minimumRequired(), {
    message: 'Not enough participants',
  });
});

minLength()とmaxLength()

minLength()とmaxLength()バリデーションルールは、文字列と配列に対して機能します:

import {Component, signal} from '@angular/core';
import {form, FormField, minLength, maxLength} from '@angular/forms/signals';

@Component({
  selector: 'app-password-form',
  imports: [FormField],
  template: `
    <form novalidate>
      <label>
        Password
        <input type="password" [formField]="passwordForm.password" />
      </label>

      <label>
        Bio
        <textarea [formField]="passwordForm.bio"></textarea>
      </label>
    </form>
  `,
})
export class PasswordFormComponent {
  passwordModel = signal({
    password: '',
    bio: '',
  });

  passwordForm = form(this.passwordModel, (schemaPath) => {
    minLength(schemaPath.password, 8, {message: 'Password must be at least 8 characters'});
    maxLength(schemaPath.password, 100, {message: 'Password is too long'});

    maxLength(schemaPath.bio, 500, {message: 'Bio cannot exceed 500 characters'});
  });
}

文字列の場合、「length」は文字数を意味します。配列の場合、「length」は要素数を意味します。

pattern()

pattern()バリデーションルールは、正規表現に対してバリデーションを行います:

import {Component, signal} from '@angular/core';
import {form, FormField, pattern} from '@angular/forms/signals';

@Component({
  selector: 'app-phone-form',
  imports: [FormField],
  template: `
    <form novalidate>
      <label>
        Phone Number
        <input [formField]="phoneForm.phone" placeholder="555-123-4567" />
      </label>

      <label>
        Postal Code
        <input [formField]="phoneForm.postalCode" placeholder="12345" />
      </label>
    </form>
  `,
})
export class PhoneFormComponent {
  phoneModel = signal({
    phone: '',
    postalCode: '',
  });

  phoneForm = form(this.phoneModel, (schemaPath) => {
    pattern(schemaPath.phone, /^\d{3}-\d{3}-\d{4}$/, {
      message: 'Phone must be in format: 555-123-4567',
    });

    pattern(schemaPath.postalCode, /^\d{5}$/, {
      message: 'Postal code must be 5 digits',
    });
  });
}

一般的なパターン:

パターンの種類 正規表現 例
電話番号 /^\d{3}-\d{3}-\d{4}$/ 555-123-4567
郵便番号 (米国) /^\d{5}$/ 12345
英数字 /^[a-zA-Z0-9]+$/ abc123
URLセーフ /^[a-zA-Z0-9_-]+$/ my-url_123

配列アイテムのバリデーション

フォームには、ネストされたオブジェクトの配列を含めることができます(例: 注文アイテムのリスト)。配列内の各アイテムにバリデーションルールを適用するには、スキーマ関数内でapplyEach()を使用します。applyEach()は配列パスを反復処理し、各アイテムのパスを提供します。このパスでは、トップレベルのフィールドと同様にバリデーターを適用できます。

import {Component, signal} from '@angular/core';
import {applyEach, FormField, form, min, required, SchemaPathTree} from '@angular/forms/signals';

type Item = {name: string; quantity: number};

interface Order {
  title: string;
  description: string;
  items: Item[];
}

function ItemSchema(item: SchemaPathTree<Item>) {
  required(item.name, {message: 'Item name is required'});
  min(item.quantity, 1, {message: 'Quantity must be at least 1'});
}

@Component(/* ... */)
export class OrderComponent {
  orderModel = signal<Order>({
    title: '',
    description: '',
    items: [{name: '', quantity: 0}],
  });

  orderForm = form(this.orderModel, (schemaPath) => {
    required(schemaPath.title);
    required(schemaPath.description);

    applyEach(schemaPath.items, ItemSchema);
  });
}

バリデーションエラー

バリデーションルールが失敗すると、何が問題だったかを説明するエラーオブジェクトが生成されます。エラーの構造を理解することは、ユーザーに明確なフィードバックを提供するのに役立ちます。

エラーの構造

各バリデーションエラーオブジェクトには、以下のプロパティが含まれています:

プロパティ 説明
kind 失敗したバリデーションルール(例: "required", "email", "minLength")
message オプションの人間が読める形式のエラーメッセージ

組み込みのバリデーションルールは、自動的にkindプロパティを設定します。messageプロパティはオプションで、バリデーションルールのオプションを通じてカスタムメッセージを提供できます。

カスタムエラーメッセージ

すべての組み込みバリデーションルールは、カスタムエラーテキストのためにmessageオプションを受け入れます:

import {Component, signal} from '@angular/core';
import {form, FormField, required, minLength} from '@angular/forms/signals';

@Component({
  selector: 'app-signup',
  imports: [FormField],
  template: `
    <form novalidate>
      <label>
        Username
        <input [formField]="signupForm.username" />
      </label>

      <label>
        Password
        <input type="password" [formField]="signupForm.password" />
      </label>
    </form>
  `,
})
export class SignupComponent {
  signupModel = signal({
    username: '',
    password: '',
  });

  signupForm = form(this.signupModel, (schemaPath) => {
    required(schemaPath.username, {
      message: 'Please choose a username',
    });

    required(schemaPath.password, {
      message: 'Password cannot be empty',
    });
    minLength(schemaPath.password, 12, {
      message: 'Password must be at least 12 characters for security',
    });
  });
}

カスタムメッセージは、明確で具体的であり、ユーザーに問題の修正方法を伝えるべきです。「無効な入力」の代わりに、「セキュリティのため、パスワードは12文字以上である必要があります」のようにします。

フィールドごとの複数のエラー

フィールドに複数のバリデーションルールがある場合、各バリデーションルールは独立して実行され、エラーを生成する可能性があります:

signupForm = form(this.signupModel, (schemaPath) => {
  required(schemaPath.email, {message: 'Email is required'});
  email(schemaPath.email, {message: 'Enter a valid email address'});
  minLength(schemaPath.email, 5, {message: 'Email is too short'});
});

emailフィールドが空の場合、required()エラーのみが表示されます。ユーザーが"a@b"と入力すると、email()とminLength()の両方のエラーが表示されます。すべてのバリデーションルールが実行され、最初の失敗でバリデーションが停止することはありません。

TIP: テンプレートでtouched() && invalid()パターンを使用すると、ユーザーがフィールドを操作する前にエラーが表示されるのを防ぐことができます。バリデーションエラーの表示に関する包括的なガイダンスについては、フィールド状態管理ガイドを参照してください。

カスタムバリデーションルール

組み込みのバリデーションルールは一般的なケースを処理しますが、ビジネスルール、複雑なフォーマット、またはドメイン固有の制約のために、カスタムバリデーションロジックが必要になることがよくあります。

validate()の使用

validate()関数はカスタムバリデーションルールを作成します。これは、フィールドコンテキストにアクセスし、以下の値を返すバリデーター関数を受け取ります:

戻り値 意味
エラーオブジェクト 値は無効です
null または undefined 値は有効です
import {Component, signal} from '@angular/core';
import {form, FormField, validate} from '@angular/forms/signals';

@Component({
  selector: 'app-url-form',
  imports: [FormField],
  template: `
    <form novalidate>
      <label>
        Website URL
        <input [formField]="urlForm.website" />
      </label>
    </form>
  `,
})
export class UrlFormComponent {
  urlModel = signal({website: ''});

  urlForm = form(this.urlModel, (schemaPath) => {
    validate(schemaPath.website, ({value}) => {
      if (!value().startsWith('https://')) {
        return {
          kind: 'https',
          message: 'URL must start with https://',
        };
      }

      return null;
    });
  });
}

バリデーター関数は、以下のプロパティを持つFieldContextオブジェクトを受け取ります:

プロパティ 型 説明
value Signal 現在のフィールド値を含むSignal
state FieldState フィールドの状態への参照
fieldTree FieldTree フィールドツリーへの参照
valueOf() Method パスで指定された他のフィールドの値を取得します
stateOf() Method パスで指定された他のフィールドの状態を取得します
fieldTreeOf() Method パスで指定された他のフィールドのフィールドツリーを取得します
pathKeys Signal ルートから現在のフィールドまでのパスキー

NOTE: 子フィールドにはkeyシグナルもあり、配列アイテムのフィールドにはkeyとindexの両方のシグナルがあります。

バリデーションが失敗した場合はkindとmessageを持つエラーオブジェクトを返します。バリデーションが成功した場合はnullまたはundefinedを返します。

validateTree()の使用

validateTree()関数は、複数のフィールドをターゲットにしたり、サブツリー全体に複雑なバリデーションロジックを提供したりできるカスタムバリデーションルールを作成します。

import {Component, model} from '@angular/core';
import {form, FormField, validateTree} from '@angular/forms/signals';

interface User {
  firstName: string;
  lastName: string;
}

@Component({/* ... */})
export class UserFormComponent {
  readonly userModel = model<User>({
    firstName: '',
    lastName: '',
  });

  userForm = form(this.userModel, (path) => {
    validateTree(path, (ctx) => {
      if (ctx.valueOf(path.firstName).length < 5) {
        return {
          kind: 'minLength5',
          message: 'First name must be at least 5 characters',
          fieldTree: ctx.fieldTree.lastName,
        };
      }

      return null;
    });
  });
}

validateTree()バリデーター関数は、validate()と同じFieldContextオブジェクトを受け取ります。

再利用可能なバリデーションルール

validate()をラップして、再利用可能なバリデーションルール関数を作成します:

function url(path: SchemaPath<string>, options?: {message?: string}) {
  validate(path, ({value}) => {
    try {
      new URL(value());
      return null;
    } catch {
      return {
        kind: 'url',
        message: options?.message || 'Enter a valid URL',
      };
    }
  });
}

function phoneNumber(path: SchemaPath<string>, options?: {message?: string}) {
  validate(path, ({value}) => {
    const phoneRegex = /^\d{3}-\d{3}-\d{4}$/;

    if (!phoneRegex.test(value())) {
      return {
        kind: 'phoneNumber',
        message: options?.message || 'Phone must be in format: 555-123-4567',
      };
    }

    return null;
  });
}

カスタムバリデーションルールは、組み込みのバリデーションルールと同じように使用できます:

urlForm = form(this.urlModel, (schemaPath) => {
  url(schemaPath.website, {message: 'Please enter a valid website URL'});
  phoneNumber(schemaPath.phone);
});

クロスフィールドバリデーション

クロスフィールドバリデーションは、複数のフィールド値を比較または関連付けます。

クロスフィールドバリデーションの一般的なシナリオは、パスワードの確認です:

import {Component, signal} from '@angular/core';
import {form, FormField, required, minLength, validate} from '@angular/forms/signals';

@Component({
  selector: 'app-password-change',
  imports: [FormField],
  template: `
    <form novalidate>
      <label>
        New Password
        <input type="password" [formField]="passwordForm.password" />
      </label>

      <label>
        Confirm Password
        <input type="password" [formField]="passwordForm.confirmPassword" />
      </label>

      <button type="submit">Change Password</button>
    </form>
  `,
})
export class PasswordChangeComponent {
  passwordModel = signal({
    password: '',
    confirmPassword: '',
  });

  passwordForm = form(this.passwordModel, (schemaPath) => {
    required(schemaPath.password, {message: 'Password is required'});
    minLength(schemaPath.password, 8, {message: 'Password must be at least 8 characters'});

    required(schemaPath.confirmPassword, {message: 'Please confirm your password'});

    validate(schemaPath.confirmPassword, ({value, valueOf}) => {
      const confirmPassword = value();
      const password = valueOf(schemaPath.password);

      if (confirmPassword !== password) {
        return {
          kind: 'passwordMismatch',
          message: 'Passwords do not match',
        };
      }

      return null;
    });
  });
}

確認用のバリデーションルールはvalueOf(schemaPath.password)を使用してパスワードフィールドの値にアクセスし、確認用の値と比較します。このバリデーションルールはリアクティブに実行されます - どちらかのパスワードが変更されると、バリデーションが自動的に再実行されます。

条件付きバリデーション

バリデーションルールは、特定の条件下でのみ適用すべき場合があります。たとえば、注文が国際配送される場合にのみ配送先住所をバリデーションする、あるいは共用体型のフィールドのバリアントごとに異なるルールセットを適用するといったケースです。

バリデーションルールはスキーマ関数内に存在するため、スキーマを構成する同じ構造的な関数を使って条件付きで適用します:

  • applyWhen()を使用して、他のフィールドの値を含むリアクティブなフォーム状態に基づいてルールのグループを有効化します。
  • applyWhenValue()を使用して、フィールド自身の値に基づいてルールを適用します。述語が型ガードである場合、ルールは絞り込まれた値の型として扱われます。これにより、判別共用体やその他のバリアント型をバリデーションするための推奨される方法となります。

再利用可能なスキーマや判別共用体を含む完全な例については、スキーマとスキーマの合成可能性ガイドを参照してください。

非同期バリデーション

非同期バリデーションは、サーバーでのユーザー名の利用可能性のチェックやAPIに対するバリデーションなど、外部データソースを必要とするバリデーションを処理します。

validateHttp()の使い方

validateHttp()関数は、HTTPベースのバリデーションを実行します:

import {Component, signal} from '@angular/core';
import {form, FormField, required, validateHttp} from '@angular/forms/signals';

@Component({
  selector: 'app-username-form',
  imports: [FormField],
  template: `
    <form novalidate>
      <label>
        Username
        <input [formField]="usernameForm.username" />

        @if (usernameForm.username().pending()) {
          <span class="checking">Checking availability...</span>
        }
      </label>
    </form>
  `,
})
export class UsernameFormComponent {
  usernameModel = signal({username: ''});

  usernameForm = form(this.usernameModel, (schemaPath) => {
    required(schemaPath.username, {message: 'Username is required'});

    validateHttp(schemaPath.username, {
      request: ({value}) => `/api/check-username?username=${value()}`,
      onSuccess: (response: any) => {
        if (response.taken) {
          return {
            kind: 'usernameTaken',
            message: 'Username is already taken',
          };
        }
        return null;
      },
      onError: (error) => ({
        kind: 'networkError',
        message: 'Could not verify username availability',
      }),
    });
  });
}

validateHttp()バリデーションルール:

  1. request関数によって返されるURLまたはリクエストを呼び出します
  2. onSuccessを使用して、成功レスポンスをバリデーションエラーまたはnullにマッピングします
  3. onErrorを使用して、リクエストの失敗(ネットワークエラー、HTTPエラー)を処理します
  4. リクエストが進行中の間、pending()をtrueに設定します
  5. すべての同期バリデーションルールが成功した後にのみ実行されます

ペンディング状態

非同期バリデーションの実行中、フィールドのpending()シグナルはtrueを返します。これを使用してローディングインジケーターを表示します:

@if (form.username().pending()) {
  <span class="spinner">Checking...</span>
}

valid()シグナルは、まだエラーがない場合でも、バリデーションがペンディング中の間はfalseを返します。invalid()シグナルは、エラーが存在する場合にのみtrueを返します。

スキーマバリデーションライブラリとの統合

シグナルフォームは、ZodやValibotのようなStandard Schemaに準拠したライブラリに対する組み込みサポートを提供しています。統合はvalidateStandardSchema関数によって提供されます。これにより、シグナルフォームのリアクティブなバリデーションの利点を維持しながら、既存のスキーマを使用できます。

import {form, validateStandardSchema} from '@angular/forms/signals';
import * as z from 'zod';

// スキーマを定義
const userSchema = z.object({
  email: z.email(),
  password: z.string().min(8),
});

// シグナルフォームで使用
const userForm = form(signal({email: '', password: ''}), (schemaPath) => {
  validateStandardSchema(schemaPath, userSchema);
});

ダイナミックスキーマ

依存関係が変更されたときにバリデーションスキーマが自動的に更新されるように、静的なスキーマの代わりにシグナルを渡すことができます。

import {Component, computed, signal} from '@angular/core';
import {form, FormField, validateStandardSchema} from '@angular/forms/signals';
import z from 'zod';

@Component({/* ... */})
export class DynamicSchema {
  model = signal({document: '', type: 'dni'});

  // Schema reacts automatically to type changes
  schema = computed(() =>
    z.object({
      document:
        this.model().type === 'dni'
          ? z.string().length(8, 'DNI must be 8 digits')
          : z.string().min(12, 'Passport must be at least 12 characters'),
    }),
  );

  f = form(this.model, (p) => validateStandardSchema(p, () => this.schema()));
}

次のステップ

このガイドでは、バリデーションルールの作成と適用について説明しました。関連ガイドでは、シグナルフォームの他の側面について解説します: