// registration.model.ts
export interface RegistrationData {
email: string;
password: string;
confirmPassword: string;
acceptedTerms: boolean;
}
Essa interface reflete o que normalmente seria enviado para uma API de back-end. Não há duplicação de estado, nenhum objeto de “valor de formulário” separado e nenhum mapeamento necessário no momento do envio.
Criando o formulário apoiado por sinal
O próprio formulário é criado no componente usando um sinal gravável como fonte da verdade. O form() A função anexa validação semântica do formulário, estado do campo e envio a esse sinal.
// registration.component.ts
import { CommonModule } from "@angular/common";
import { Component, signal } from "@angular/core";
import {
email,
form,
FormField,
required,
submit,
} from "@angular/forms/signals";
import { RegistrationData } from "./registration.model";
@Component({
selector: "app-registration",
imports: (FormField, CommonModule),
templateUrl: "./registration.html",
styleUrl: "./registration.css",
})
export class Registration {
readonly model = signal({
email: "",
password: "",
confirmPassword: "",
acceptedTerms: false,
});
readonly registrationForm = form(this.model, (schema) => {
required(schema.email, { message: "Email is required" });
email(schema.email, { message: "Enter a valid email address" });
required(schema.password, { message: "Password is required" });
required(schema.confirmPassword, {
message: "Please confirm your password",
});
required(schema.acceptedTerms, {
message: "You must accept the terms to continue",
});
});
async onSubmit(event?: Event) {
event?.preventDefault();
await submit(this.registrationForm, (value) => {
console.log(value());
// Mock Server Call
return Promise.resolve((
{
kind: "EmailAlreadyExists",
field: this.registrationForm.email,
error: { kind: "server", message: "Email already taken" },
},
));
});
}
}
Várias decisões de design são dignas de nota.
