IslomDevIslomDev
Booster
Imtihon
Booster
Imtihon
  • Angular Intervyu Tayyorgarlik
  • JavaScript / TypeScript

    • JavaScript / TypeScript
    • Asoslar (JavaScript)
    • Asinxronlik
    • Prototip va OOP
    • TypeScript
    • Performance
  • Algoritmlash

    • Algoritmlash
    • Murakkablik tahlili
    • Ma'lumot tuzilmalari
    • Qidiruv va Saralash
    • Algoritmik paradigmalar
    • Amaliy masalalar
  • Angular — Boshlang'ich

    • Angular — Boshlang'ich
    • Component
    • Template
    • Change Detection
    • Advanced Component
  • Angular — Service va DI

    • Angular — Service va DI
    • Service asoslari
    • HTTP
    • Hierarchical DI
    • Advanced DI
    • State management (service)
  • Angular — Versiyalar

    • Angular — Versiyalar
    • Angular 12–13
    • Angular 14
    • Angular 15
    • Angular 16
    • Angular 17
    • Angular 18+
  • Angular — Directive

    • Angular — Directive
    • Built-in Directives
    • Custom Attribute Directive
    • Custom Structural Directive
    • Advanced
  • Angular — RxJS

    • Angular — RxJS
    • Observable asoslari
    • Asosiy operatorlar
    • Higher-order operatorlar
    • Combination operatorlar
    • Subject turlari
    • Xato va xotira
    • Advanced
  • Angular — Pipe

    • Angular — Pipe
    • Built-in Pipes
    • Custom Pipe
    • Performance
  • Angular — Forms

    • Angular — Forms
    • Template-driven Forms
    • Reactive Forms
    • Validators
    • Advanced
  • Angular — NgModule

    • Angular — NgModule
    • NgModule asoslari
    • Module arxitekturasi
    • Lazy Loading
    • Standalone vs NgModule
  • Angular — Sintaksis va Clean Code

    • Angular — Sintaksis va Clean Code
    • Template sintaksisi
    • Angular 17+ yangi sintaksis
    • Komponent arxitekturasi
    • Performance pattern'lar
    • SOLID va Clean Code
    • Testing

Validators

Daraja:

Angular built-in va custom validatorlar orqali forma ma'lumotlarini tekshiradi. Sync — darhol, async — server tekshiruvi (username bandligi).

Sync custom validator — ValidatorFn

Middle

Nima bu?

ValidatorFn — (control: AbstractControl) => ValidationErrors | null signature'li funksiya. null — valid, ob'ekt — xato ({ myError: true }). Bir nechta validator array sifatida beriladi.

Kod misoli

import { AbstractControl, ValidationErrors, ValidatorFn, Validators } from '@angular/forms';

// O'zbekiston telefon raqami
export function uzbekPhoneValidator(): ValidatorFn {
  return (control: AbstractControl): ValidationErrors | null => {
    const value = control.value as string;
    if (!value) return null; // required alohida
    const valid = /^\+998[0-9]{9}$/.test(value);
    return valid ? null : { uzbekPhone: { value } };
  };
}

// Parol kuchliligi
export function passwordStrengthValidator(): ValidatorFn {
  return (control: AbstractControl): ValidationErrors | null => {
    const v = control.value as string;
    if (!v) return null;
    const hasUpper = /[A-Z]/.test(v);
    const hasDigit = /[0-9]/.test(v);
    const hasSpecial = /[!@#$%^&*]/.test(v);
    if (hasUpper && hasDigit && hasSpecial) return null;
    return { passwordStrength: { hasUpper, hasDigit, hasSpecial } };
  };
}

@Component({
  selector: 'app-signup-form',
  standalone: true,
  imports: [ReactiveFormsModule],
  template: `
    <form [formGroup]="form">
      <input formControlName="phone" />
      @if (form.controls.phone.errors?.['uzbekPhone']) {
        <span>Format: +998XXXXXXXXX</span>
      }
      <input formControlName="password" type="password" />
    </form>
  `,
})
export class SignupFormComponent {
  form = new FormGroup({
    phone: new FormControl('', [Validators.required, uzbekPhoneValidator()]),
    password: new FormControl('', [Validators.required, passwordStrengthValidator()]),
  });
}

Imtihonda

Savol: Custom validator required o'rniga bo'sh qiymatni invalid qilsa?

Javob: Noto'g'ri pattern. Bo'sh qiymat uchun return null — Validators.required alohida ishlasin. Aks holda required va custom validator ziddiyat qiladi.

Yodlash uchun

ValidatorFn: valid → null, invalid → `{ errorKey: payload }`. Bo'sh qiymat → null (required alohida).

Async custom validator — AsyncValidatorFn

Middle

Nima bu?

AsyncValidatorFn — (control) => ObservableValidationErrors | null | Promise...``. Server tekshiruvi: username bandligi, email mavjudligi. Control pending: true holatiga o'tadi. Sync validatorlardan alohida asyncValidators array'ida beriladi.

Kod misoli

import { AbstractControl, AsyncValidatorFn, ValidationErrors } from '@angular/forms';
import { inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { map, catchError, of, debounceTime, switchMap, first } from 'rxjs';

@Injectable({ providedIn: 'root' })
export class UsernameCheckService {
  private http = inject(HttpClient);

  isAvailable(username: string): Observable<boolean> {
    return this.http.get<{ available: boolean }>(`/api/check-username/${username}`).pipe(
      map((res) => res.available),
      catchError(() => of(false))
    );
  }
}

export function uniqueUsernameValidator(): AsyncValidatorFn {
  const service = inject(UsernameCheckService);

  return (control: AbstractControl): Observable<ValidationErrors | null> => {
    if (!control.value) return of(null);

    return of(control.value).pipe(
      debounceTime(400),
      switchMap((username) => service.isAvailable(username)),
      map((available) => (available ? null : { usernameTaken: true })),
      first()
    );
  };
}

@Component({
  selector: 'app-username-field',
  standalone: true,
  imports: [ReactiveFormsModule],
  template: `
    <input [formControl]="username" />
    @if (username.pending) { <span>Tekshirilmoqda...</span> }
    @if (username.errors?.['usernameTaken']) { <span>Bu login band</span> }
  `,
})
export class UsernameFieldComponent {
  username = new FormControl('', {
    validators: Validators.required,
    asyncValidators: uniqueUsernameValidator(),
    updateOn: 'blur',
  });
}

Imtihonda

Savol: Async validator nega first() bilan tugatiladi?

Javob: Observable complete bo'lishi kerak — aks holda control doim pending holatda qoladi. first() birinchi qiymatdan keyin complete qiladi.

Savol: Sync va async validatorlar bir vaqtda ishga tushadimi?

Javob: Yo'q. Angular avval barcha sync validatorlarni tekshiradi; ular hech biri xato qaytarmasa, keyin async validatorlar ishga tushadi. Shuning uchun required xato bo'lsa, uniqueUsernameValidator HTTP so'rovi umuman jo'natilmaydi — bu tarmoq trafigini behuda sarflashdan saqlaydi, lekin submit paytida form.pending === true bo'lishi mumkinligini va tugmani shunga qarab disable qilish kerakligini unutmaslik kerak.

Yodlash uchun

Async: alohida `asyncValidators`. `pending` holat. Observable complete bo'lishi shart. Debounce + updateOn blur. Sync avval, async keyin ishga tushadi.

Cross-field validator — FormGroup darajasida

MiddleSenior

Nima bu?

Ba'zi validatsiya bir nechta field'ga bog'liq: parol tasdiqlash, sana oralig'i, "kamida bittasi to'ldirilsin". Bunday validator FormGroup darajasida beriladi — control o'rniga butun group tekshiriladi.

Kod misoli

function passwordMatchValidator(): ValidatorFn {
  return (group: AbstractControl): ValidationErrors | null => {
    const password = group.get('password')?.value;
    const confirm = group.get('confirmPassword')?.value;
    if (password !== confirm) {
      group.get('confirmPassword')?.setErrors({ passwordMismatch: true });
      return { passwordMismatch: true };
    }
    // confirmPassword'dagi eski xatoni tozalash
    const confirmCtrl = group.get('confirmPassword');
    if (confirmCtrl?.hasError('passwordMismatch')) {
      confirmCtrl.setErrors(null);
    }
    return null;
  };
}

function dateRangeValidator(): ValidatorFn {
  return (group: AbstractControl): ValidationErrors | null => {
    const start = group.get('startDate')?.value;
    const end = group.get('endDate')?.value;
    if (start && end && new Date(start) > new Date(end)) {
      return { dateRange: { start, end } };
    }
    return null;
  };
}

@Component({
  selector: 'app-password-form',
  standalone: true,
  imports: [ReactiveFormsModule],
  template: `
    <form [formGroup]="form">
      <input formControlName="password" type="password" />
      <input formControlName="confirmPassword" type="password" />
      @if (form.errors?.['passwordMismatch']) {
        <span>Parollar mos kelmadi</span>
      }
    </form>
  `,
})
export class PasswordFormComponent {
  form = new FormGroup(
    {
      password: new FormControl('', Validators.required),
      confirmPassword: new FormControl('', Validators.required),
    },
    { validators: passwordMatchValidator() }
  );
}

Imtihonda

Savol: Cross-field xato qayerda ko'rsatiladi — field yoki group?

Javob: form.errors — group darajasidagi xato. Field-specific xato uchun control.setErrors() ham ishlatiladi. UI: ikkala joyda ham ko'rsatish mumkin.

Yodlash uchun

Cross-field → FormGroup `{ validators: fn }`. `form.errors` group xatosi. Field xatosi: `get('field')?.errors`.

Validator composition — Validators.compose

Middle

Nima bu?

Bir nechta sync validatorni bitta ValidatorFn ga birlashtirish. Validators.compose([v1, v2]) — birinchi xato topilganda to'xtaydi. Validators.composeAsync — async uchun. Array [v1, v2] bilan deyarli bir xil (Angular ichida compose ishlatadi).

Kod misoli

const emailOrPhoneValidator = Validators.compose([
  Validators.required,
  (control: AbstractControl): ValidationErrors | null => {
    const v = control.value as string;
    const isEmail = Validators.email({ value: v } as AbstractControl) === null;
    const isPhone = /^\+998[0-9]{9}$/.test(v);
    return isEmail || isPhone ? null : { emailOrPhone: true };
  },
]);

@Component({
  selector: 'app-contact-field',
  standalone: true,
  imports: [ReactiveFormsModule],
  template: `<input [formControl]="contact" />`,
})
export class ContactFieldComponent {
  contact = new FormControl('', {
    validators: emailOrPhoneValidator,
    nonNullable: true,
  });

  // Qayta ishlatiladigan validator to'plami
  static readonly userValidators = Validators.compose([
    Validators.required,
    Validators.minLength(3),
    Validators.maxLength(20),
    Validators.pattern(/^[a-zA-Z0-9_]+$/),
  ]);
}

Imtihonda

Savol: [Validators.required, myValidator] va Validators.compose([...]) farqi?

Javob: Amaliy jihatdan bir xil — Angular array'ni ichida compose qiladi. compose qayta ishlatiladigan validator export qilishda qulay.

Yodlash uchun

Array validator = compose. Birinchi xato qaytadi. Async uchun `composeAsync` yoki `asyncValidators` array.
Prev
Reactive Forms
Next
Advanced