docs: update signal form tutorials to use FormField

This commit is contained in:
Matthieu Riegler 2026-01-22 14:05:46 +01:00 committed by Andrew Scott
parent d1135f5840
commit ddd3198dc2
22 changed files with 72 additions and 72 deletions

View file

@ -1,6 +1,6 @@
import {ChangeDetectionStrategy, Component, signal} from '@angular/core';
import {email, form, FormField, required, submit} from '@angular/forms/signals';
import {bootstrapApplication} from '@angular/platform-browser';
import {Component, signal, ChangeDetectionStrategy} from '@angular/core';
import {form, Field, required, email, debounce, submit} from '@angular/forms/signals';
interface LoginData {
email: string;
@ -14,7 +14,7 @@ interface LoginData {
<div>
<label>
Email:
<input type="email" [field]="loginForm.email" />
<input type="email" [formField]="loginForm.email" />
</label>
@if (loginForm.email().invalid()) {
@ -29,7 +29,7 @@ interface LoginData {
<div>
<label>
Password:
<input type="password" [field]="loginForm.password" />
<input type="password" [formField]="loginForm.password" />
</label>
@if (loginForm.password().invalid()) {
@ -45,7 +45,7 @@ interface LoginData {
</form>
`,
styleUrl: 'main.css',
imports: [Field],
imports: [FormField],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class LoginApp {

View file

@ -1,11 +1,11 @@
# Connect your form to the template
Now, you need to connect your form to the template using the `[field]` directive. This creates two-way data binding between your form model and the input elements.
Now, you need to connect your form to the template using the `[formField]` directive. This creates two-way data binding between your form model and the input elements.
In this lesson, you'll learn how to:
- Import the `Field` directive
- Use the `[field]` directive to bind form fields to inputs
- Import the `FormField` directive
- Use the `[formField]` directive to bind form fields to inputs
- Connect text inputs and checkboxes to your form
- Display form field values in the template
@ -15,17 +15,17 @@ Let's wire up the template!
<docs-workflow>
<docs-step title="Import the Field directive">
Import the `Field` directive from `@angular/forms/signals` and add it to your component's imports array:
<docs-step title="Import the FormField directive">
Import the `FormField` directive from `@angular/forms/signals` and add it to your component's imports array:
```ts
import { form, Field } from '@angular/forms/signals';
import { form, FormField } from '@angular/forms/signals';
@Component({
selector: 'app-root',
templateUrl: './app.html',
styleUrl: './app.css',
imports: [Field],
imports: [FormField],
changeDetection: ChangeDetectionStrategy.OnPush,
})
```
@ -33,29 +33,29 @@ import { form, Field } from '@angular/forms/signals';
</docs-step>
<docs-step title="Bind the email field">
In your template, add the `[field]` directive to the email input:
In your template, add the `[formField]` directive to the email input:
```html
<input type="email" [field]="loginForm.email" />
<input type="email" [formField]="loginForm.email" />
```
The `loginForm.email` expression accesses the email field from your form.
</docs-step>
<docs-step title="Bind the password field">
Add the `[field]` directive to the password input:
Add the `[formField]` directive to the password input:
```html
<input type="password" [field]="loginForm.password" />
<input type="password" [formField]="loginForm.password" />
```
</docs-step>
<docs-step title="Bind the checkbox field">
Add the `[field]` directive to the checkbox input:
Add the `[formField]` directive to the checkbox input:
```html
<input type="checkbox" [field]="loginForm.rememberMe" />
<input type="checkbox" [formField]="loginForm.rememberMe" />
```
</docs-step>
@ -74,6 +74,6 @@ Form field values are signals, so the displayed values update automatically as y
</docs-workflow>
Great work! You've connected your form to the template and displayed the form values. The `[field]` directive handles two-way data binding automatically - as you type, the `loginModel` signal updates, and the displayed values update immediately.
Great work! You've connected your form to the template and displayed the form values. The `[formField]` directive handles two-way data binding automatically - as you type, the `loginModel` signal updates, and the displayed values update immediately.
Next, you'll learn [how to add validation to your form](/tutorials/signal-forms/3-add-validation)!

View file

@ -2,20 +2,20 @@
<div>
<label>
Email
<input type="email" [field]="loginForm.email" />
<input type="email" [formField]="loginForm.email" />
</label>
</div>
<div>
<label>
Password
<input type="password" [field]="loginForm.password" />
<input type="password" [formField]="loginForm.password" />
</label>
</div>
<div>
<label>
<input type="checkbox" [field]="loginForm.rememberMe" />
<input type="checkbox" [formField]="loginForm.rememberMe" />
Remember me
</label>
</div>

View file

@ -1,5 +1,5 @@
import {Component, signal, ChangeDetectionStrategy} from '@angular/core';
import {form, Field} from '@angular/forms/signals';
import {ChangeDetectionStrategy, Component, signal} from '@angular/core';
import {form, FormField} from '@angular/forms/signals';
interface LoginData {
email: string;
@ -11,7 +11,7 @@ interface LoginData {
selector: 'app-root',
templateUrl: './app.html',
styleUrl: './app.css',
imports: [Field],
imports: [FormField],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class App {

View file

@ -2,7 +2,7 @@
<div>
<label>
Email
<!-- TODO: Add [field]="loginForm.email" directive -->
<!-- TODO: Add [formField]="loginForm.email" directive -->
<input type="email" />
</label>
</div>
@ -10,14 +10,14 @@
<div>
<label>
Password
<!-- TODO: Add [field]="loginForm.password" directive -->
<!-- TODO: Add [formField]="loginForm.password" directive -->
<input type="password" />
</label>
</div>
<div>
<label>
<!-- TODO: Add [field]="loginForm.rememberMe" directive -->
<!-- TODO: Add [formField]="loginForm.rememberMe" directive -->
<input type="checkbox" />
Remember me
</label>

View file

@ -1,5 +1,5 @@
import {Component, signal, ChangeDetectionStrategy} from '@angular/core';
// TODO: Import Field directive from @angular/forms/signals
import {ChangeDetectionStrategy, Component, signal} from '@angular/core';
// TODO: Import FormField directive from @angular/forms/signals
import {form} from '@angular/forms/signals';
interface LoginData {
@ -12,7 +12,7 @@ interface LoginData {
selector: 'app-root',
templateUrl: './app.html',
styleUrl: './app.css',
// TODO: Add Field to imports array
// TODO: Add FormField to imports array
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class App {

View file

@ -18,7 +18,7 @@ Let's add validation!
Import the `required` and `email` validators from `@angular/forms/signals`:
```ts
import {form, Field, required, email} from '@angular/forms/signals';
import {form, FormField, required, email} from '@angular/forms/signals';
```
</docs-step>

View file

@ -2,20 +2,20 @@
<div>
<label>
Email
<input type="email" [field]="loginForm.email" />
<input type="email" [formField]="loginForm.email" />
</label>
</div>
<div>
<label>
Password
<input type="password" [field]="loginForm.password" />
<input type="password" [formField]="loginForm.password" />
</label>
</div>
<div>
<label>
<input type="checkbox" [field]="loginForm.rememberMe" />
<input type="checkbox" [formField]="loginForm.rememberMe" />
Remember me
</label>
</div>

View file

@ -1,5 +1,5 @@
import {Component, signal, ChangeDetectionStrategy} from '@angular/core';
import {form, Field, required, email} from '@angular/forms/signals';
import {ChangeDetectionStrategy, Component, signal} from '@angular/core';
import {email, form, FormField, required} from '@angular/forms/signals';
interface LoginData {
email: string;
@ -11,7 +11,7 @@ interface LoginData {
selector: 'app-root',
templateUrl: './app.html',
styleUrl: './app.css',
imports: [Field],
imports: [FormField],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class App {

View file

@ -2,20 +2,20 @@
<div>
<label>
Email
<input type="email" [field]="loginForm.email" />
<input type="email" [formField]="loginForm.email" />
</label>
</div>
<div>
<label>
Password
<input type="password" [field]="loginForm.password" />
<input type="password" [formField]="loginForm.password" />
</label>
</div>
<div>
<label>
<input type="checkbox" [field]="loginForm.rememberMe" />
<input type="checkbox" [formField]="loginForm.rememberMe" />
Remember me
</label>
</div>

View file

@ -1,6 +1,6 @@
import {Component, signal, ChangeDetectionStrategy} from '@angular/core';
import {ChangeDetectionStrategy, Component, signal} from '@angular/core';
// TODO: Import required and email validators
import {form, Field} from '@angular/forms/signals';
import {form, FormField} from '@angular/forms/signals';
interface LoginData {
email: string;
@ -12,7 +12,7 @@ interface LoginData {
selector: 'app-root',
templateUrl: './app.html',
styleUrl: './app.css',
imports: [Field],
imports: [FormField],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class App {

View file

@ -21,7 +21,7 @@ Below the email input, add conditional error display. This will only show errors
```angular-html
<label>
Email
<input type="email" [field]="loginForm.email" />
<input type="email" [formField]="loginForm.email" />
</label>
@if (loginForm.email().invalid() && loginForm.email().touched()) {
<div class="error">
@ -41,7 +41,7 @@ Below the password input, add the same pattern for password errors:
```angular-html
<label>
Password
<input type="password" [field]="loginForm.password" />
<input type="password" [formField]="loginForm.password" />
</label>
@if (loginForm.password().invalid() && loginForm.password().touched()) {
<div class="error">

View file

@ -2,7 +2,7 @@
<div>
<label>
Email
<input type="email" [field]="loginForm.email" />
<input type="email" [formField]="loginForm.email" />
</label>
@if (loginForm.email().invalid() && loginForm.email().touched()) {
<div class="error">
@ -16,7 +16,7 @@
<div>
<label>
Password
<input type="password" [field]="loginForm.password" />
<input type="password" [formField]="loginForm.password" />
</label>
@if (loginForm.password().invalid() && loginForm.password().touched()) {
<div class="error">
@ -29,7 +29,7 @@
<div>
<label>
<input type="checkbox" [field]="loginForm.rememberMe" />
<input type="checkbox" [formField]="loginForm.rememberMe" />
Remember me
</label>
</div>

View file

@ -1,5 +1,5 @@
import {Component, signal, ChangeDetectionStrategy} from '@angular/core';
import {form, Field, required, email} from '@angular/forms/signals';
import {ChangeDetectionStrategy, Component, signal} from '@angular/core';
import {email, form, FormField, required} from '@angular/forms/signals';
interface LoginData {
email: string;
@ -11,7 +11,7 @@ interface LoginData {
selector: 'app-root',
templateUrl: './app.html',
styleUrl: './app.css',
imports: [Field],
imports: [FormField],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class App {

View file

@ -2,7 +2,7 @@
<div>
<label>
Email
<input type="email" [field]="loginForm.email" />
<input type="email" [formField]="loginForm.email" />
</label>
<!-- TODO: Add @if to show errors when invalid and touched -->
<!-- TODO: Use @for to loop through loginForm.email().errors() -->
@ -12,7 +12,7 @@
<div>
<label>
Password
<input type="password" [field]="loginForm.password" />
<input type="password" [formField]="loginForm.password" />
</label>
<!-- TODO: Add @if to show errors when invalid and touched -->
<!-- TODO: Use @for to loop through loginForm.password().errors() -->
@ -21,7 +21,7 @@
<div>
<label>
<input type="checkbox" [field]="loginForm.rememberMe" />
<input type="checkbox" [formField]="loginForm.rememberMe" />
Remember me
</label>
</div>

View file

@ -1,5 +1,5 @@
import {Component, signal, ChangeDetectionStrategy} from '@angular/core';
import {form, Field, required, email} from '@angular/forms/signals';
import {ChangeDetectionStrategy, Component, signal} from '@angular/core';
import {email, form, FormField, required} from '@angular/forms/signals';
interface LoginData {
email: string;
@ -11,7 +11,7 @@ interface LoginData {
selector: 'app-root',
templateUrl: './app.html',
styleUrl: './app.css',
imports: [Field],
imports: [FormField],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class App {

View file

@ -19,7 +19,7 @@ Let's complete the form!
Import the `submit` function from `@angular/forms/signals`:
```ts
import {form, Field, required, email, submit} from '@angular/forms/signals';
import {form, FormField, required, email, submit} from '@angular/forms/signals';
```
</docs-step>

View file

@ -2,7 +2,7 @@
<div>
<label>
Email
<input type="email" [field]="loginForm.email" />
<input type="email" [formField]="loginForm.email" />
</label>
@if (loginForm.email().invalid() && loginForm.email().touched()) {
<div class="error">
@ -16,7 +16,7 @@
<div>
<label>
Password
<input type="password" [field]="loginForm.password" />
<input type="password" [formField]="loginForm.password" />
</label>
@if (loginForm.password().invalid() && loginForm.password().touched()) {
<div class="error">
@ -29,7 +29,7 @@
<div>
<label>
<input type="checkbox" [field]="loginForm.rememberMe" />
<input type="checkbox" [formField]="loginForm.rememberMe" />
Remember me
</label>
</div>

View file

@ -1,5 +1,5 @@
import {Component, signal, ChangeDetectionStrategy} from '@angular/core';
import {form, Field, required, email, submit} from '@angular/forms/signals';
import {ChangeDetectionStrategy, Component, signal} from '@angular/core';
import {email, form, FormField, required, submit} from '@angular/forms/signals';
interface LoginData {
email: string;
@ -11,7 +11,7 @@ interface LoginData {
selector: 'app-root',
templateUrl: './app.html',
styleUrl: './app.css',
imports: [Field],
imports: [FormField],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class App {

View file

@ -3,7 +3,7 @@
<div>
<label>
Email
<input type="email" [field]="loginForm.email" />
<input type="email" [formField]="loginForm.email" />
</label>
@if (loginForm.email().invalid() && loginForm.email().touched()) {
<div class="error">
@ -17,7 +17,7 @@
<div>
<label>
Password
<input type="password" [field]="loginForm.password" />
<input type="password" [formField]="loginForm.password" />
</label>
@if (loginForm.password().invalid() && loginForm.password().touched()) {
<div class="error">
@ -30,7 +30,7 @@
<div>
<label>
<input type="checkbox" [field]="loginForm.rememberMe" />
<input type="checkbox" [formField]="loginForm.rememberMe" />
Remember me
</label>
</div>

View file

@ -1,6 +1,6 @@
import {Component, signal, ChangeDetectionStrategy} from '@angular/core';
import {ChangeDetectionStrategy, Component, signal} from '@angular/core';
// TODO: Import submit function
import {form, Field, required, email} from '@angular/forms/signals';
import {email, form, FormField, required} from '@angular/forms/signals';
interface LoginData {
email: string;
@ -12,7 +12,7 @@ interface LoginData {
selector: 'app-root',
templateUrl: './app.html',
styleUrl: './app.css',
imports: [Field],
imports: [FormField],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class App {

View file

@ -7,7 +7,7 @@ You've completed the Signal Forms tutorial and built a complete login form from
Throughout this tutorial, you learned the fundamentals of Angular Signal Forms:
1. **Form Models** - Creating type-safe form data with signals and the `form()` function
2. **Field Binding** - Using the `[field]` directive for two-way data binding and displaying the field with `value()`
2. **Field Binding** - Using the `[formField]` directive for two-way data binding and displaying the field with `value()`
3. **Validation** - Applying built-in validators (such as `required()`, `email()`) with custom messages
4. **Error Display** - Showing validation errors conditionally based on field state
5. **Form Submission** - Handling form submission with the `submit()` function