// registration.mannequin.ts
export interface RegistrationData {
e-mail: string;
password: string;
confirmPassword: string;
acceptedTerms: boolean;
}
This interface mirrors what would sometimes be despatched to a back-end API. There isn’t any duplication of state, no separate “type worth” object, and no mapping required at submission time.
Creating the signal-backed type
The shape itself is created within the element utilizing a writable sign because the supply of fact. The type() perform attaches type semantics validation, subject state, and submission to that sign.
// registration.element.ts
import { CommonModule } from "@angular/frequent";
import { Part, sign } from "@angular/core";
import {
e-mail,
type,
FormField,
required,
submit,
} from "@angular/kinds/indicators";
import { RegistrationData } from "./registration.mannequin";
@Part({
selector: "app-registration",
imports: [FormField, CommonModule],
templateUrl: "./registration.html",
styleUrl: "./registration.css",
})
export class Registration {
readonly mannequin = sign({
e-mail: "",
password: "",
confirmPassword: "",
acceptedTerms: false,
});
readonly registrationForm = type(this.mannequin, (schema) => {
required(schema.e-mail, { message: "E-mail is required" });
e-mail(schema.e-mail, { message: "Enter a legitimate e-mail handle" });
required(schema.password, { message: "Password is required" });
required(schema.confirmPassword, {
message: "Please affirm your password",
});
required(schema.acceptedTerms, {
message: "It's essential to settle for the phrases to proceed",
});
});
async onSubmit(occasion?: Occasion) {
occasion?.preventDefault();
await submit(this.registrationForm, (worth) => {
console.log(worth());
// Mock Server Name
return Promise.resolve([
{
kind: "EmailAlreadyExists",
field: this.registrationForm.email,
error: { kind: "server", message: "Email already taken" },
},
]);
});
}
}
A number of design choices are value noting.
