Signal формы в Angular
Angular сигнал формы – это мощный инструмент, позволяющий создавать интерактивные веб-приложения с простотой и элегантностью. Он реализует реактивный подход к обработке данных, обеспечивая мгновенное обновление пользовательского интерфейса при изменении значений в формах. Благодаря сигналам, разработчики могут легко отслеживать состояние форм и управлять их поведением, что делает процесс разработки более предсказуемым и эффективным. Используя Angular сигнал формы, вы сможете создавать более отзывчивые и динамичные приложения, которые помогут пользователям без усилий взаимодействовать с вашими сервисами.
В этом уроке мы рассмотрим создание формы пользователя с использованием сигнальных форм. На практическом примере разберём:
- создание модели формы через signal();
- связывание модели с формой при помощи form();
- добавление встроенных валидаторов через required();
- написание собственных правил проверки через validate();
- отправку формы и обработку введённых данных.
В результате вы увидите, как сигнальные формы позволяют сделать код более читаемым, типобезопасным и удобным для поддержки по сравнению с привычным подходом на Reactive Forms.
users.component.ts
import {Component, injectAsync, input, InputSignal, signal} from '@angular/core';
import {form, FormField, required, validate} from '@angular/forms/signals';
import {FormsModule} from '@angular/forms';
import {JsonPipe} from '@angular/common';
interface UserForm {
userName: string;
role: 'admin' | 'editor' | 'viewer' | 'moderator';
}
@Component({
selector: 'app-users',
imports: [
FormField,
FormsModule,
JsonPipe
],
templateUrl: './users.component.html',
styleUrl: './users.component.css',
})
export class UsersComponent {
public users: InputSignal<string[]> = input<string[]>([]);
protected loginFormModel = signal<UserForm>({
userName: '',
role: 'admin',
})
protected loginForm = form(this.loginFormModel, (schema) => {
required(schema.userName, {
message: 'User name is required',
error: 'userNameRequired'
}),
validate(schema.userName, ({value}) => {
if(value().trim().length > 5) {
return {
kind: 'tooLong',
message: 'Too long username'
}
}
return null;
})
})
protected usersService = injectAsync(() =>
import('../users.service').then(s => s.UsersService));
protected async updateUsers() {
const users = await this.usersService();
users.updateUsers();
}
protected submitForm(event: Event) {
event.preventDefault();
console.log(this.loginFormModel());
console.log(this.loginForm.userName().valid());
}
}
users.component.html
<p>users works!</p>
<ul>
@for (user of users(); track user) {
<li>{{user}}</li>
}
</ul>
<button (click)="updateUsers()">Update users</button>
<form (submit)="submitForm($event)">
<p>
<input type="text" [formField]="loginForm.userName">
</p>
@if(loginForm.userName().touched() && loginForm.userName().invalid()) {
<p>Username is invalid</p>
<p>{{loginForm.userName().errors() | json}}</p>
}
<p>
</p>
<p>
<select>
<option value="admin">Admin</option>
<option value="editor">Editor</option>
<option value="viewer">Viewer</option>
<option value="moderator">Moderator</option>
</select>
</p>
<button>Submot form</button>
</form>
<hr>
Username: {{loginForm.userName().value() | json}}
Username touched: {{loginForm.userName().touched()}}
Username valid: {{loginForm.userName().valid()}}
Role: {{loginForm.role().value() | json}}
0 Comments