Angular フォームの探索: シグナルを使用した新しい選択肢
Angular フォームの探索: シグナルを使用した新しい選択肢
Angular の世界では、単純なログイン ページを作成する場合でも、より複雑なユーザー プロファイル インターフェイスを作成する場合でも、フォームはユーザーとの対話に不可欠です。 Angular は伝統的に、テンプレート駆動型フォーム と リアクティブ フォーム という 2 つの主要なアプローチを提供しています。 Angular Reactive Forms に関する以前のシリーズでは、リアクティブ フォームの機能を活用して複雑なロジックを管理し、動的フォームを作成し、カスタム フォーム コントロールを構築する方法を検討しました。
反応性を管理するための新しいツールである シグナル は、Angular のバージョン 16 で導入され、それ以来 Angular メンテナーの注目を集めており、バージョン 17 で安定しました。シグナルを使用すると、状態の変更を処理できます。宣言的に、テンプレート駆動型のシンプルさとリアクティブ型の堅牢な反応性を組み合わせたエキサイティングな代替手段を提供します。この記事では、Angular の単純なフォームと複雑なフォームの両方にシグナルがどのように反応性を追加できるかを検証します。
要約: Angular Forms のアプローチ
シグナルを使用してテンプレート駆動のフォームを強化するというトピックに入る前に、Angular の従来のフォームのアプローチを簡単にまとめてみましょう。
-
テンプレート駆動フォーム: ngModel などのディレクティブを使用して HTML テンプレートで直接定義されるこれらのフォームは、セットアップが簡単で、単純なフォームに最適です。ただし、より複雑なシナリオに必要なきめ細かい制御が提供されない場合があります。
テンプレート駆動型フォームの最小限の例を次に示します:
<form (ngSubmit)="onSubmit()"> <label for="name">Name:</label> <input> </li> </ol> <pre class="brush:php;toolbar:false">```typescript import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html' }) export class AppComponent { name = ''; onSubmit() { console.log(this.name); } } ```
ログイン後にコピー-
リアクティブ フォーム: Angular の FormGroup、FormControl、FormArray クラスを使用して、コンポーネント クラスでプログラムによって管理されます。リアクティブ フォームでは、フォームの状態と検証を詳細に制御できます。 Angular Reactive Forms に関する以前の記事で説明したように、このアプローチは複雑なフォームに適しています。
そして、これがリアクティブフォームの最小限の例です:
import { Component } from '@angular/core'; import { FormGroup, FormControl } from '@angular/forms'; @Component({ selector: 'app-root', templateUrl: './app.component.html' }) export class AppComponent { form = new FormGroup({ name: new FormControl('') }); onSubmit() { console.log(this.form.value); } }
ログイン後にコピー
```html <form [formGroup]="form" (ngSubmit)="onSubmit()"> <label for="name">Name:</label> <input> <h2> Introducing Signals as a New Way to Handle Form Reactivity </h2> <p>With the release of Angular 16, signals have emerged as a new way to manage reactivity. Signals provide a declarative approach to state management, making your code more predictable and easier to understand. When applied to forms, signals can enhance the simplicity of template-driven forms while offering the reactivity and control typically associated with reactive forms.</p> <p>Let’s explore how signals can be used in both simple and complex form scenarios.</p> <h3> Example 1: A Simple Template-Driven Form with Signals </h3> <p>Consider a basic login form. Typically, this would be implemented using template-driven forms like this:<br> </p> <pre class="brush:php;toolbar:false"><!-- login.component.html --> <form name="form" (ngSubmit)="onSubmit()"> <label for="email">E-mail</label> <input type="email"> <pre class="brush:php;toolbar:false">// login.component.ts import { Component } from "@angular/core"; @Component({ selector: "app-login", templateUrl: "./login.component.html", }) export class LoginComponent { public email: string = ""; public password: string = ""; onSubmit() { console.log("Form submitted", { email: this.email, password: this.password }); } }
ログイン後にコピーこのアプローチは単純なフォームにはうまく機能しますが、シグナルを導入することで、シンプルさを維持しながらリアクティブ機能を追加できます。
// login.component.ts import { Component, computed, signal } from "@angular/core"; import { FormsModule } from "@angular/forms"; @Component({ selector: "app-login", standalone: true, templateUrl: "./login.component.html", imports: [FormsModule], }) export class LoginComponent { // Define signals for form fields public email = signal(""); public password = signal(""); // Define a computed signal for the form value public formValue = computed(() => { return { email: this.email(), password: this.password(), }; }); public isFormValid = computed(() => { return this.email().length > 0 && this.password().length > 0; }); onSubmit() { console.log("Form submitted", this.formValue()); } }
ログイン後にコピー<!-- login.component.html --> <form name="form" (ngSubmit)="onSubmit()"> <label for="email">E-mail</label> <input type="email"> <p>In this example, the form fields are defined as signals, allowing for reactive updates whenever the form state changes. The formValue signal provides a computed value that reflects the current state of the form. This approach offers a more declarative way to manage form state and reactivity, combining the simplicity of template-driven forms with the power of signals.</p> <p>You may be tempted to define the form directly as an object inside a signal. While such an approach may seem more concise, typing into the individual fields does not dispatch reactivity updates, which is usually a deal breaker. Here’s an example StackBlitz with a component suffering from such an issue:</p> <p>Therefore, if you'd like to react to changes in the form fields, it's better to define each field as a separate signal. By defining each form field as a separate signal, you ensure that changes to individual fields trigger reactivity updates correctly. </p> <h3> Example 2: A Complex Form with Signals </h3> <p>You may see little benefit in using signals for simple forms like the login form above, but they truly shine when handling more complex forms. Let's explore a more intricate scenario - a user profile form that includes fields like firstName, lastName, email, phoneNumbers, and address. The phoneNumbers field is dynamic, allowing users to add or remove phone numbers as needed.</p> <p>Here's how this form might be defined using signals:<br> </p> <pre class="brush:php;toolbar:false">// user-profile.component.ts import { JsonPipe } from "@angular/common"; import { Component, computed, signal } from "@angular/core"; import { FormsModule, Validators } from "@angular/forms"; @Component({ standalone: true, selector: "app-user-profile", templateUrl: "./user-profile.component.html", styleUrls: ["./user-profile.component.scss"], imports: [FormsModule, JsonPipe], }) export class UserProfileComponent { public firstName = signal(""); public lastName = signal(""); public email = signal(""); // We need to use a signal for the phone numbers, so we get reactivity when typing in the input fields public phoneNumbers = signal([signal("")]); public street = signal(""); public city = signal(""); public state = signal(""); public zip = signal(""); public formValue = computed(() => { return { firstName: this.firstName(), lastName: this.lastName(), email: this.email(), // We need to do a little mapping here, so we get the actual value for the phone numbers phoneNumbers: this.phoneNumbers().map((phoneNumber) => phoneNumber()), address: { street: this.street(), city: this.city(), state: this.state(), zip: this.zip(), }, }; }); public formValid = computed(() => { const { firstName, lastName, email, phoneNumbers, address } = this.formValue(); // Regex taken from the Angular email validator const EMAIL_REGEXP = /^(?=.{1,254}$)(?=.{1,64}@)[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/; const isEmailFormatValid = EMAIL_REGEXP.test(email); return ( firstName.length > 0 && lastName.length > 0 && email.length > 0 && isEmailFormatValid && phoneNumbers.length > 0 && // Check if all phone numbers are valid phoneNumbers.every((phoneNumber) => phoneNumber.length > 0) && address.street.length > 0 && address.city.length > 0 && address.state.length > 0 && address.zip.length > 0 ); }); addPhoneNumber() { this.phoneNumbers.update((phoneNumbers) => { phoneNumbers.push(signal("")); return [...phoneNumbers]; }); } removePhoneNumber(index: number) { this.phoneNumbers.update((phoneNumbers) => { phoneNumbers.splice(index, 1); return [...phoneNumbers]; }); } }
ログイン後にコピーphoneNumbers フィールドが信号配列の信号として定義されていることに注意してください。この構造により、個々の電話番号の変更を追跡し、フォームの状態を事後的に更新できます。 addPhoneNumber メソッドとremovePhoneNumber メソッドは、phoneNumbers 信号配列を更新し、フォーム内の反応性の更新をトリガーします。
<!-- user-profile.component.html --> <blockquote> <p>テンプレートでは、phoneNumbers 信号配列を使用して電話番号入力フィールドを動的にレンダリングします。 addPhoneNumber メソッドとremovePhoneNumber メソッドを使用すると、ユーザーは電話番号をリアクティブに追加または削除し、フォームの状態を更新できます。 track 関数の使用法に注目してください。これは、ngFor ディレクティブがphoneNumbers 配列への変更を正しく追跡するために必要です。</p> </blockquote> <p>これは、試してみたい複雑なフォームの例の StackBlitz デモです:</p> <h3> シグナルによるフォームの検証 </h3> <p>検証はどのフォームにとっても重要であり、ユーザー入力が送信前に必要な基準を満たしていることを確認します。シグナルを使用すると、検証は事後的かつ宣言的な方法で処理できます。上記の複雑なフォームの例では、すべてのフィールドが特定の検証基準を満たしているかどうかをチェックする、formValid という計算信号を実装しました。</p> <p>検証ロジックは、有効な電子メール形式をチェックしたり、すべての必須フィールドが入力されていることを確認したりするなど、さまざまなルールに合わせて簡単にカスタマイズできます。検証にシグナルを使用すると、検証ルールが明確に定義され、フォーム フィールドの変更に自動的に反応するため、より保守しやすくテストしやすいコードを作成できます。別のユーティリティに抽象化して、さまざまな形式で再利用できるようにすることもできます。</p> <p>複雑なフォームの例では、formValid 信号により、すべての必須フィールドが入力されていることを確認し、電子メールと電話番号の形式が検証されます。</p> <p>この検証のアプローチは少し単純なので、実際のフォームフィールドとより適切に接続する必要があります。多くのユースケースで機能しますが、場合によっては、明示的な「シグナルフォーム」サポートが Angular に追加されるまで待ったほうがよい場合もあります。 Tim Deschryver は、検証を含む信号形式に関するいくつかの抽象化の実装を開始し、それに関する記事を書きました。将来、このようなものが Angular に追加されるかどうか見てみましょう。</p> <h3> 信号を角のある形式で使用する理由 </h3> <p>Angular でのシグナルの採用により、フォームの状態と反応性を管理するための強力な新しい方法が提供されます。シグナルは、テンプレート駆動型フォームとリアクティブ フォームの長所を組み合わせることで、複雑なフォーム処理を簡素化できる柔軟な宣言型アプローチを提供します。 Angular 形式でシグナルを使用する主な利点をいくつか示します:</p> <ol> <li><p><strong>宣言的な状態管理</strong>: シグナルを使用すると、フォーム フィールドと計算値を宣言的に定義できるため、コードがより予測可能になり、理解しやすくなります。</p></li> <li><p><strong>反応性</strong>: シグナルはフォーム フィールドに反応的な更新を提供し、フォームの状態の変更によって反応性の更新が自動的にトリガーされるようにします。</p></li> <li><p><strong>粒度の高い制御</strong>: シグナルを使用すると、フォーム フィールドを粒度の高いレベルで定義でき、フォームの状態と検証をきめ細かく制御できます。</p></li> <li><p><strong>動的フォーム</strong>: シグナルを使用すると、動的に追加または削除できるフィールドを持つ動的フォームを作成でき、複雑なフォーム シナリオを処理する柔軟な方法を提供します。</p></li> <li><p><strong>シンプルさ</strong>: シグナルは、従来のリアクティブ フォームよりもシンプルで簡潔なフォームの状態管理方法を提供し、複雑なフォームの構築と維持を容易にします。</p></li> </ol> <h3> 結論 </h3> <p>前回の記事では、動的なフォームの構築からカスタム フォーム コントロールに至るまで、Angular リアクティブ フォームの強力な機能について説明しました。シグナルの導入により、Angular 開発者は、テンプレート駆動型フォームのシンプルさとリアクティブ フォームの反応性を統合する新しいツールを利用できるようになりました。</p> <p>多くのユースケースではリアクティブ フォームが正当化されますが、シグナルは、より直接的で宣言的なアプローチを必要とする Angular アプリケーションでフォームの状態を管理するための新鮮で強力な代替手段を提供します。 Angular は進化し続けるため、これらの新機能を試してみることは、より保守しやすく、パフォーマンスの高いアプリケーションを構築するのに役立ちます。</p> <p>コーディングを楽しんでください!</p>
ログイン後にコピー -
以上がAngular フォームの探索: シグナルを使用した新しい選択肢の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック











Pythonは、スムーズな学習曲線と簡潔な構文を備えた初心者により適しています。 JavaScriptは、急な学習曲線と柔軟な構文を備えたフロントエンド開発に適しています。 1。Python構文は直感的で、データサイエンスやバックエンド開発に適しています。 2。JavaScriptは柔軟で、フロントエンドおよびサーバー側のプログラミングで広く使用されています。

Web開発におけるJavaScriptの主な用途には、クライアントの相互作用、フォーム検証、非同期通信が含まれます。 1)DOM操作による動的なコンテンツの更新とユーザーインタラクション。 2)ユーザーエクスペリエンスを改善するためにデータを提出する前に、クライアントの検証が実行されます。 3)サーバーとのリフレッシュレス通信は、AJAXテクノロジーを通じて達成されます。

現実世界でのJavaScriptのアプリケーションには、フロントエンドとバックエンドの開発が含まれます。 1)DOM操作とイベント処理を含むTODOリストアプリケーションを構築して、フロントエンドアプリケーションを表示します。 2)node.jsを介してRestfulapiを構築し、バックエンドアプリケーションをデモンストレーションします。

JavaScriptエンジンが内部的にどのように機能するかを理解することは、開発者にとってより効率的なコードの作成とパフォーマンスのボトルネックと最適化戦略の理解に役立つためです。 1)エンジンのワークフローには、3つの段階が含まれます。解析、コンパイル、実行。 2)実行プロセス中、エンジンはインラインキャッシュや非表示クラスなどの動的最適化を実行します。 3)ベストプラクティスには、グローバル変数の避け、ループの最適化、constとletsの使用、閉鎖の過度の使用の回避が含まれます。

PythonとJavaScriptには、コミュニティ、ライブラリ、リソースの観点から、独自の利点と短所があります。 1)Pythonコミュニティはフレンドリーで初心者に適していますが、フロントエンドの開発リソースはJavaScriptほど豊富ではありません。 2)Pythonはデータサイエンスおよび機械学習ライブラリで強力ですが、JavaScriptはフロントエンド開発ライブラリとフレームワークで優れています。 3)どちらも豊富な学習リソースを持っていますが、Pythonは公式文書から始めるのに適していますが、JavaScriptはMDNWebDocsにより優れています。選択は、プロジェクトのニーズと個人的な関心に基づいている必要があります。

開発環境におけるPythonとJavaScriptの両方の選択が重要です。 1)Pythonの開発環境には、Pycharm、Jupyternotebook、Anacondaが含まれます。これらは、データサイエンスと迅速なプロトタイピングに適しています。 2)JavaScriptの開発環境には、フロントエンドおよびバックエンド開発に適したnode.js、vscode、およびwebpackが含まれます。プロジェクトのニーズに応じて適切なツールを選択すると、開発効率とプロジェクトの成功率が向上する可能性があります。

CとCは、主に通訳者とJITコンパイラを実装するために使用されるJavaScriptエンジンで重要な役割を果たします。 1)cは、JavaScriptソースコードを解析し、抽象的な構文ツリーを生成するために使用されます。 2)Cは、Bytecodeの生成と実行を担当します。 3)Cは、JITコンパイラを実装し、実行時にホットスポットコードを最適化およびコンパイルし、JavaScriptの実行効率を大幅に改善します。

JavaScriptは、Webサイト、モバイルアプリケーション、デスクトップアプリケーション、サーバー側のプログラミングで広く使用されています。 1)Webサイト開発では、JavaScriptはHTMLおよびCSSと一緒にDOMを運用して、JQueryやReactなどのフレームワークをサポートします。 2)ReactNativeおよびIonicを通じて、JavaScriptはクロスプラットフォームモバイルアプリケーションを開発するために使用されます。 3)電子フレームワークにより、JavaScriptはデスクトップアプリケーションを構築できます。 4)node.jsを使用すると、JavaScriptがサーバー側で実行され、高い並行リクエストをサポートします。
