Template-driven Forms
Template-driven formlar — HTML template ichida ngModel va built-in validatorlar bilan boshqariladi. Kichik, oddiy formalar uchun tez va qulay. Angular form holatini (valid, dirty, touched) avtomatik kuzatadi.
FormsModule import
Nima bu?
Template-driven formlar uchun @angular/forms dan FormsModule import qilinadi. Bu ngModel, ngForm, ngModelGroup directive'larini faollashtiradi. Standalone component'da imports: [FormsModule].
Kod misoli
import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
@Component({
selector: 'app-contact',
standalone: true,
imports: [FormsModule],
template: `
<form #f="ngForm" (ngSubmit)="onSubmit(f)">
<input name="email" ngModel required email #email="ngModel" />
<button type="submit" [disabled]="f.invalid">Yuborish</button>
</form>
`,
})
export class ContactComponent {
onSubmit(form: NgForm): void {
console.log(form.value); // { email: '...' }
}
}
Imtihonda
Savol: Template-driven va Reactive formlar bir vaqtda ishlatiladimi?
Javob: Ha, lekin bir formada aralashtirish tavsiya etilmaydi. FormsModule + ReactiveFormsModule ikkalasi import qilinishi mumkin — turli component'larda.
Yodlash uchun
ngModel — two-way binding
Nima bu?
[(ngModel)] — two-way data binding: input qiymati component property bilan sinxron. [ngModel] — one-way (component → template), (ngModelChange) — event (template → component). Form ichida name attribute majburiy (ngForm tracking uchun).
Kod misoli
@Component({
selector: 'app-profile',
standalone: true,
imports: [FormsModule],
template: `
<!-- Two-way -->
<input name="username" [(ngModel)]="user.name" />
<!-- One-way + event (ekvivalent) -->
<input name="email" [ngModel]="user.email" (ngModelChange)="user.email = $event" />
<p>Salom, {{ user.name }}!</p>
`,
})
export class ProfileComponent {
user = { name: '', email: '' };
}
Imtihonda
Savol: ngModel form tashqarisida ishlatilsa name kerakmi?
Javob: Form ichida ha — name bo'lmasa "Cannot track by name" xabari chiqadi. Form tashqarisida standalone ngModel uchun name shart emas, lekin [ngModelOptions]="{standalone: true}" kerak bo'lishi mumkin.
Yodlash uchun
ngForm — form holati (valid, dirty, touched)
Nima bu?
form #f="ngForm" — butun formning holatini beradi. Har bir control va form uchun Angular holat flag'lari kuzatadi:
valid/invalid— validatorlar o'tdimipristine/dirty— foydalanuvchi o'zgartirdimitouched/untouched— fokus chiqdimipending— async validator kutyaptimi
Kod misoli
@Component({
selector: 'app-register',
standalone: true,
imports: [FormsModule],
template: `
<form #regForm="ngForm" (ngSubmit)="submit(regForm)">
<input
name="password"
type="password"
ngModel
required
minlength="8"
#pwd="ngModel"
/>
@if (pwd.invalid && pwd.touched) {
<span class="error">Kamida 8 belgi kerak</span>
}
<button type="submit" [disabled]="regForm.invalid || regForm.pending">
Ro'yxatdan o'tish
</button>
<p>Form dirty: {{ regForm.dirty }}</p>
<p>Form valid: {{ regForm.valid }}</p>
</form>
`,
})
export class RegisterComponent {
submit(form: NgForm): void {
if (form.valid) {
console.log(form.value);
}
}
}
Imtihonda
Savol: Xato xabarini qachon ko'rsatish kerak — dirty yoki touched?
Javob: touched — foydalanuvchi field'dan chiqqanda. Ba'zi loyihalar dirty && touched yoki submit bosilganda ham ko'rsatadi. Eng yaxshi UX: (invalid && touched) || form.submitted.
Yodlash uchun
Built-in validators — required, minlength, maxlength, email, pattern
Nima bu?
Template-driven formlarda validatorlar HTML attribute sifatida qo'shiladi. Angular ularni avtomatik qo'llaydi va errors ob'ektida natija saqlanadi.
| Validator | Attribute | errors kaliti |
|---|---|---|
| required | required | { required: true } |
| minlength | minlength="8" | { minlength: { requiredLength, actualLength } } |
| maxlength | maxlength="100" | { maxlength: {...} } |
email | { email: true } | |
| pattern | pattern="regex" | { pattern: {...} } |
Kod misoli
@Component({
selector: 'app-signup',
standalone: true,
imports: [FormsModule],
template: `
<form #f="ngForm">
<input name="phone" ngModel required pattern="^\\+998[0-9]{9}$" #phone="ngModel" />
<input name="bio" ngModel maxlength="200" #bio="ngModel" />
<input name="contactEmail" ngModel email #contactEmail="ngModel" />
@if (phone.errors?.['pattern'] && phone.touched) {
<span>Telefon: +998XXXXXXXXX formatida</span>
}
@if (bio.errors?.['maxlength']) {
<span>Maksimum 200 belgi ({{ bio.errors?.['maxlength'].actualLength }}/200)</span>
}
</form>
`,
})
export class SignupComponent {}
Imtihonda
Savol: required va bo'sh string — validmi?
Javob: Bo'sh string required uchun invalid. Faqat probel bo'lsa ham invalid (whitespace hisoblanadi).
Yodlash uchun
Xato ko'rsatish — ngModel.errors
Nima bu?
Har bir NgModel directive #ref="ngModel" orqali control holatiga kirish beradi. ref.errors — validator xatolari ob'ekti yoki null (valid bo'lsa). Template'da shartli xabar ko'rsatish uchun ishlatiladi.
Kod misoli
@Component({
selector: 'app-login',
standalone: true,
imports: [FormsModule],
template: `
<form #loginForm="ngForm" (ngSubmit)="login(loginForm)">
<div>
<input name="username" ngModel required minlength="3" #username="ngModel" />
@if (username.invalid && (username.touched || loginForm.submitted)) {
@if (username.errors?.['required']) {
<span class="error">Login majburiy</span>
}
@if (username.errors?.['minlength']) {
<span class="error">Kamida 3 belgi</span>
}
}
</div>
<div>
<input name="password" type="password" ngModel required #password="ngModel" />
@if (password.errors?.['required'] && password.touched) {
<span class="error">Parol majburiy</span>
}
</div>
<button type="submit">Kirish</button>
</form>
`,
})
export class LoginComponent {
login(form: NgForm): void {
if (form.invalid) return;
// API chaqiruv
}
}
Imtihonda
Savol: errors null bo'lishi mumkinmi valid field'da?
Javob: Ha. Valid control uchun errors === null. Shuning uchun errors?.['required'] optional chaining ishlatiladi.
Yodlash uchun
