Login
A minimal centered login card with email/password fields, validation errors, and a social-login separator.
Preview
Try submitting with empty fields or an invalid email to see <ng-oat-form-error> in action.
html
<form [formRoot]="loginForm" (ngSubmit)="onSubmit()" class="card max-w-sm w-100">
<header>
<h3 class="mb-0">Welcome back</h3>
<p class="text-light mb-0">Sign in to your account</p>
</header>
<div class="vstack gap-3">
<div>
<ng-oat-input label="Email" type="email" [formField]="loginForm.email" />
<ng-oat-form-error [control]="loginForm.email" />
</div>
<div>
<ng-oat-input label="Password" type="password" [formField]="loginForm.password" />
<ng-oat-form-error [control]="loginForm.password" />
</div>
<div class="hstack justify-between">
<ng-oat-checkbox label="Remember me" [formField]="loginForm.remember" />
<a href="#" class="text-small">Forgot password?</a>
</div>
<button type="submit" class="btn">Sign In</button>
<ng-oat-separator label="or" />
<button class="btn outline" type="button">Continue with Google</button>
</div>
<footer class="text-center text-small text-light">
Don't have an account? <a href="#">Sign up</a>
</footer>
</form>SFC Source
typescript
import { Component, signal } from '@angular/core';
import { FormField, FormRoot, form, schema, required, email, minLength } from '@angular/forms/signals';
import { NgOatInput, NgOatCheckbox, NgOatFormError, NgOatSeparator } from '@letsprogram/ng-oat';
@Component({
selector: 'app-login',
imports: [FormField, FormRoot, NgOatInput, NgOatCheckbox, NgOatFormError, NgOatSeparator],
template: `
<div class="flex justify-center p-8">
<form [formRoot]="loginForm" (ngSubmit)="onSubmit()" class="card max-w-sm w-100">
<header>
<h3 class="mb-0">Welcome back</h3>
<p class="text-light mb-0">Sign in to your account</p>
</header>
<div class="vstack gap-3">
<div>
<ng-oat-input label="Email" type="email" placeholder="you@example.com" [formField]="loginForm.email" />
<ng-oat-form-error [control]="loginForm.email" />
</div>
<div>
<ng-oat-input label="Password" type="password" placeholder="••••••••" [formField]="loginForm.password" />
<ng-oat-form-error [control]="loginForm.password" />
</div>
<div class="hstack justify-between">
<ng-oat-checkbox label="Remember me" [formField]="loginForm.remember" />
<a href="#" class="text-small">Forgot password?</a>
</div>
<button type="submit" class="btn">Sign In</button>
<ng-oat-separator label="or" />
<button class="btn outline" type="button">Continue with Google</button>
</div>
<footer class="text-center text-small text-light">
Don't have an account? <a href="#">Sign up</a>
</footer>
</form>
</div>
`,
})
export class LoginComponent {
private model = signal({ email: '', password: '', remember: false });
loginForm = form(this.model, schema($ => {
required($.email);
email($.email);
required($.password);
minLength($.password, 6);
}));
onSubmit() { console.log('Login:', this.model()); }
}