2026 Angular Formlari: Reactive Forms, Dogrulama ve Teknik Mulakat Sorulari

Tipli FormBuilder, ozel dogrulayicilar, asenkron dogrulama ve FormArray ile Angular Reactive Forms konusunda uzmanlasin. Mulakat sorulari ve Signal Forms onizlemesi iceriyor.

2026 Angular Formlari: Reactive Forms, Dogrulama ve Teknik Mulakat Sorulari

Angular Reactive Forms, 2026 yilinda kurumsal form gelistirmenin temel tasini olmaya devam ediyor ve basit giris ekranlarindan karmasik cok adimli sihirbazlara kadar olceklenebilen tip-guvenli, test edilebilir form yonetimi sagliyor. Angular 19'un gelistirilmis API'leri ve gelistirici onizlemesinde bulunan Signal Forms ile hem mevcut standardi hem de gelecekteki degisiklikleri anlamak, gelisitiricilere teknik mulakatlarda rekabet avantaji sagliyor.

Onemli Bilgi

Reactive Forms, form yapisinin TypeScript'te tanimlandigi model odakli bir yaklasim kullanir ve dogrulama zamanlami, dinamik alan manipulasyonu ve DOM etkilesimi olmadan kapsamli birim testleri uzerinde tam kontrol saglar.

Reactive Forms Mimarisi

Reactive Forms, degismez bir veri modeli uzerinde calisir. Her degisiklik yeni bir durum nesnesi olusturur ve form davranisini tahmin edilebilir ve hata ayiklanabilir kilar. Temel yapi taslari FormControl, FormGroup ve FormArray olup, bunlar FormBuilder servisi araciligiyla yonetilir.

Form modeli (TypeScript) ile sablon (HTML) arasindaki ayrim, dogrulama mantginin bagimsiz olarak test edilmesine olanak tanir. Bu mimari secim ayni zamanda backend konfigurasyonlarina dayali dinamik form olusturmaya da olanak tanir - kurumsal uygulamalarda yaygin bir gereksinim.

user-profile.component.tstypescript
import { Component, inject } from '@angular/core';
import { FormBuilder, Validators, ReactiveFormsModule } from '@angular/forms';
import { CommonModule } from '@angular/common';

@Component({
  selector: 'app-user-profile',
  standalone: true,
  imports: [CommonModule, ReactiveFormsModule],
  template: `
    <form [formGroup]="profileForm" (ngSubmit)="onSubmit()">
      <input formControlName="email" placeholder="Email" />
      <input formControlName="name" placeholder="Full Name" />
      <button type="submit" [disabled]="profileForm.invalid">Save</button>
    </form>
  `
})
export class UserProfileComponent {
  private fb = inject(FormBuilder);

  // Typed form with NonNullable configuration
  profileForm = this.fb.nonNullable.group({
    email: ['', [Validators.required, Validators.email]],
    name: ['', [Validators.required, Validators.minLength(2)]]
  });

  onSubmit() {
    // profileForm.getRawValue() returns typed object
    const data = this.profileForm.getRawValue();
    console.log(data.email, data.name); // Both are string, not string | null
  }
}

Angular 14'te tanitilan nonNullable form builder konfigurasyonu, form degerlerinden nullable tipleri ortadan kaldirir. Bu, kod tabani genelinde null kontrollerini azaltir ve form yonetimini daha tahmin edilebilir kilar.

Karmasik Is Kurallari icin Ozel Dogrulayicilar

Yerlesik dogrulayicilar yaygin senaryolari kapsarken, gercek dunya uygulamalari ozel dogrulama mantigi gerektirir. Angular hem senkron hem de asenkron dogrulayicilari destekler; asenkron dogrulayicilar kullanici adi kullanilabilirligi gibi sunucu tarafi kontrolleri icin kullanislidir.

validators/password.validator.tstypescript
import { AbstractControl, ValidationErrors, ValidatorFn } from '@angular/forms';

// Synchronous validator: password strength
export function strongPassword(): ValidatorFn {
  return (control: AbstractControl): ValidationErrors | null => {
    const value = control.value;
    if (!value) return null;

    const hasUpperCase = /[A-Z]/.test(value);
    const hasLowerCase = /[a-z]/.test(value);
    const hasNumber = /\d/.test(value);
    const hasSpecial = /[!@#$%^&*]/.test(value);
    const isLongEnough = value.length >= 8;

    const valid = hasUpperCase && hasLowerCase && hasNumber && hasSpecial && isLongEnough;
    
    return valid ? null : {
      strongPassword: {
        hasUpperCase,
        hasLowerCase,
        hasNumber,
        hasSpecial,
        isLongEnough
      }
    };
  };
}

// Cross-field validator: password confirmation
export function passwordMatch(): ValidatorFn {
  return (group: AbstractControl): ValidationErrors | null => {
    const password = group.get('password')?.value;
    const confirm = group.get('confirmPassword')?.value;
    
    return password === confirm ? null : { passwordMismatch: true };
  };
}

Dogrulayicilar tarafindan dondurlen hata nesnesi, hangi belirli kontrollerin basarisiz olduguna dair ayrintili bilgi icerebilir. Bu, genel "gecersiz sifre" geri bildirimi yerine ayrintili hata mesajlari saglar.

registration.component.tstypescript
@Component({
  selector: 'app-registration',
  standalone: true,
  imports: [CommonModule, ReactiveFormsModule],
  template: `
    <form [formGroup]="registrationForm" (ngSubmit)="register()">
      <input formControlName="password" type="password" />
      <input formControlName="confirmPassword" type="password" />
      
      @if (registrationForm.errors?.['passwordMismatch']) {
        <span class="error">Passwords do not match</span>
      }
    </form>
  `
})
export class RegistrationComponent {
  private fb = inject(FormBuilder);

  registrationForm = this.fb.nonNullable.group({
    password: ['', [Validators.required, strongPassword()]],
    confirmPassword: ['', Validators.required]
  }, { validators: passwordMatch() }); // Group-level validator
}

Grup seviyesi dogrulayicilar tum FormGroup'u alir ve birden fazla alani kapsayan dogrulama kurallarina olanak tanir. Bu model, alanlar arasi mantik gerektiren her senaryo icin gecerlidir: tarih araliklari, kosullu gereksinimler veya iliskili alan kombinasyonlari.

Asenkron Dogrulayicilar ve Debouncing

Asenkron dogrulayicilar, kullanici arayuzunu engellemeden sunucu tarafi kontrolleri gerceklestirir. Yaygin kullanim ornekleri arasinda benzersiz kullanici adlarini dogrulama, e-posta kullanilabilirligini kontrol etme veya promosyon kodlarini bir API'ye karsi dogrulama yer alir.

validators/async-validators.tstypescript
import { AbstractControl, AsyncValidatorFn, ValidationErrors } from '@angular/forms';
import { Observable, of, timer } from 'rxjs';
import { map, switchMap, catchError } from 'rxjs/operators';
import { inject } from '@angular/core';
import { UserService } from '../services/user.service';

export function uniqueEmailValidator(userService: UserService): AsyncValidatorFn {
  return (control: AbstractControl): Observable<ValidationErrors | null> => {
    if (!control.value) {
      return of(null);
    }

    // Debounce 300ms to avoid excessive API calls
    return timer(300).pipe(
      switchMap(() => userService.checkEmailAvailable(control.value)),
      map(isAvailable => isAvailable ? null : { emailTaken: true }),
      catchError(() => of(null)) // Fail open on network errors
    );
  };
}

timer kullanan debounce modeli, her tus vurusunda API isteklerini onler. switchMap operatoru, yeni giris geldiginde bekleyen istekleri iptal eder ve yalnizca en son degerin sunucu kontrolunu tetiklemesini saglar.

signup.component.tstypescript
@Component({
  selector: 'app-signup',
  standalone: true,
  imports: [CommonModule, ReactiveFormsModule],
  template: `
    <form [formGroup]="signupForm">
      <input formControlName="email" />
      @if (emailControl.pending) {
        <span>Checking availability...</span>
      }
      @if (emailControl.errors?.['emailTaken']) {
        <span class="error">This email is already registered</span>
      }
    </form>
  `
})
export class SignupComponent {
  private fb = inject(FormBuilder);
  private userService = inject(UserService);

  signupForm = this.fb.nonNullable.group({
    email: ['', 
      [Validators.required, Validators.email],
      [uniqueEmailValidator(this.userService)] // Async validator as 3rd argument
    ]
  });

  get emailControl() {
    return this.signupForm.controls.email;
  }
}

Asenkron dogrulayicilar, senkron dogrulayicilar gecildikten sonra calisir ve hatali bicimlendirilmis girisler icin gereksiz API cagrilarindan kacinir. pending durumu devam eden dogrulamayi belirtir ve sablonda yukleme gostergelerini etkinlestirir.

Angular mülakatlarında başarılı olmaya hazır mısın?

İnteraktif simülatörler, flashcards ve teknik testlerle pratik yap.

FormArray ile Dinamik Formlar

FormArray, dinamik form kontrol koleksiyonlarina olanak tanir - birden fazla adres, telefon numarasi veya siparis kalemi ekleme gibi senaryolar icin gereklidir. Her dizi elemani basit bir FormControl veya ic ice gecmis bir FormGroup olabilir.

order-form.component.tstypescript
import { Component, inject } from '@angular/core';
import { FormBuilder, FormArray, ReactiveFormsModule, Validators } from '@angular/forms';
import { CommonModule } from '@angular/common';

@Component({
  selector: 'app-order-form',
  standalone: true,
  imports: [CommonModule, ReactiveFormsModule],
  template: `
    <form [formGroup]="orderForm">
      <div formArrayName="items">
        @for (item of itemsArray.controls; track item; let i = $index) {
          <div [formGroupName]="i" class="item-row">
            <input formControlName="productName" placeholder="Product" />
            <input formControlName="quantity" type="number" />
            <input formControlName="price" type="number" />
            <button type="button" (click)="removeItem(i)">Remove</button>
          </div>
        }
      </div>
      <button type="button" (click)="addItem()">Add Item</button>
      <p>Total: {{ calculateTotal() | currency }}</p>
    </form>
  `
})
export class OrderFormComponent {
  private fb = inject(FormBuilder);

  orderForm = this.fb.group({
    items: this.fb.array<FormGroup>([])
  });

  get itemsArray(): FormArray {
    return this.orderForm.get('items') as FormArray;
  }

  addItem() {
    const itemGroup = this.fb.nonNullable.group({
      productName: ['', Validators.required],
      quantity: [1, [Validators.required, Validators.min(1)]],
      price: [0, [Validators.required, Validators.min(0)]]
    });
    this.itemsArray.push(itemGroup);
  }

  removeItem(index: number) {
    this.itemsArray.removeAt(index);
  }

  calculateTotal(): number {
    return this.itemsArray.controls.reduce((sum, control) => {
      const quantity = control.get('quantity')?.value || 0;
      const price = control.get('price')?.value || 0;
      return sum + (quantity * price);
    }, 0);
  }
}

track ile @for blogu, Angular'in tum listeyi yeniden render etmek yerine yalnizca degisen elemanlari verimli bir sekilde guncellemesini saglar. Buyuk diziler icin bu optimizasyon performansi onemli olcude arttirir.

Signal Forms: Angular Form Yonetiminin Gelecegi

Angular 20, Reactive Forms'a sinyal tabanli bir alternatif sunan Signal Forms'u gelistirici onizlemesinde tanitti. Angular 21.2, geleneksel FormGroups icinde sinyal destekli alanlara izin vererek kademeli geçis icin SignalFormControl wrapper ekledi.

signal-form-example.component.tstypescript
import { Component, signal, computed } from '@angular/core';
import { SignalFormControl } from '@angular/forms';

@Component({
  selector: 'app-signal-form',
  standalone: true,
  template: `
    <input [value]="name()" (input)="name.set($any($event.target).value)" />
    <p>Character count: {{ charCount() }}</p>
    <p>Valid: {{ isValid() }}</p>
  `
})
export class SignalFormExampleComponent {
  // Signal-based form state
  name = signal('');
  
  // Computed values automatically update
  charCount = computed(() => this.name().length);
  isValid = computed(() => this.name().length >= 3);
}

Signal Forms, valueChanges aboneliklerine olan ihtiyaci ortadan kaldirir. Computed sinyaller dogrulama durumunu ve bagimli degerleri otomatik olarak turetir ve Angular'in zoneless degisiklik algilamasiyla entegre olur. Hala gelistirici onizlemesinde olsa da, Signal Forms, Angular'da form yonetiminin gidecegi yonu temsil ediyor.

Temel fark: Reactive Forms durum degisiklikleri icin RxJS Observables kullanirken, Signal Forms Angular Signals kullanir. 2026 sonlari veya sonrasinda baslayan yeni projeler icin, Signal Forms kararli duruma ulastiginda onerilen yaklasim haline gelebilir.

Angular Forms Hakkinda Yaygin Mulakat Sorulari

Teknik mulakatlar siklikla form yonetimi bilgisini test eder. Deneyimli adaylari ayiran modeller sunlardir:

S: Form durumu sifirlamayi form kontrolu sifirlamayla nasil yonetirsiniz?

typescript
// Reset entire form to initial values
this.form.reset(); // All controls become null (or default if nonNullable)

// Reset with specific values
this.form.reset({ email: '', name: 'Guest' });

// Reset single control
this.form.controls.email.reset();

// Mark as pristine without changing values
this.form.markAsPristine();
this.form.markAsUntouched();

S: setValue ve patchValue arasindaki fark nedir?

typescript
// setValue requires ALL controls - throws if missing any
this.form.setValue({ email: 'a@b.com', name: 'Test' }); // Must include both

// patchValue allows partial updates
this.form.patchValue({ email: 'a@b.com' }); // Name unchanged

S: Form kontrolunu gonderimde degerini kaybetmeden nasil devre disi birakirsiniz?

Disabled controls excluded from form.valuetypescript
this.form.controls.email.disable();
console.log(this.form.value); // { name: 'Test' } - email missing

// Use getRawValue() to include disabled controls
console.log(this.form.getRawValue()); // { email: 'a@b.com', name: 'Test' }

Bu nüanslari anlamak pratik deneyimi gosterir. Mulakatcilar genellikle form durum yonetimindeki uc durumlar hakkinda farkindaligi arastirirlar, ozellikle devre disi birakilmis kontroller ve kismi guncellemeler etrafinda.

Angular form ile ilgili mulakat sorularinda daha derin pratik icin, Reactive Forms mulakat sorulari modulu ve Template-Driven Forms modulu incelenebilir.

Uretim Formlari icin En Iyi Uygulamalar

Uretim uygulamalari, temel form olusturmanin otesinde modeller gerektirir. Hata isleme, erisilebilirlik ve performans buyuk olcekte kritik hale gelir.

form-errors.component.tstypescript
import { Component, input } from '@angular/core';
import { AbstractControl, ValidationErrors } from '@angular/forms';

@Component({
  selector: 'app-form-errors',
  standalone: true,
  template: `
    @if (control().invalid && (control().dirty || control().touched)) {
      <div class="errors" role="alert">
        @if (control().errors?.['required']) {
          <span>This field is required</span>
        }
        @if (control().errors?.['email']) {
          <span>Enter a valid email address</span>
        }
        @if (control().errors?.['minlength']) {
          <span>Minimum {{ control().errors?.['minlength'].requiredLength }} characters</span>
        }
      </div>
    }
  `
})
export class FormErrorsComponent {
  control = input.required<AbstractControl>();
}

role="alert" ozelligi, ekran okuyucularin hata mesajlarini gorundukleri anda duyurmasini saglar. Hem dirty hem de touched kontrolu, kullanici etkilesiminden once hatalarin gosterilmesini onler ve hayal kirikligi yaratan erken dogrulama geri bildiriminden kacinir.

Alanlar arasi dogrulama ve asenkron kontroller dahil kapsamli form dogrulama modelleri icin, Angular RxJS Fundamentals modulu form durum yonetiminin altinda yatan Observable modellerini kapsar.

Sonuc

  • Reactive Forms, karmasik kurumsal uygulamalar icin uygun tip-guvenli, test edilebilir form yonetimi saglar
  • Ozel dogrulayicilar hem senkron is kurallarini hem de yerlesik debouncing ile asenkron sunucu tarafi kontrollerini destekler
  • FormArray, track araciligiyla verimli degisiklik izleme ile dinamik form koleksiyonlarina olanak tanir
  • Signal Forms (gelistirici onizlemesi), Angular'in zoneless gelecegi ile uyumlu daha basit bir reaktif model sunar
  • Uretim formlari erisilebilirlik degerlendirmeleri ve yeniden kullanilabilir hata goruntuleme bilesenleri gerektirir
  • setValue vs patchValue ve getRawValue() vs value anlayisi deneyimli adaylari ayirt eder

Pratik yapmaya başla!

Mülakat simülatörleri ve teknik testlerle bilgini test et.

Anthony Fillion-Maillet

Yazan:

Anthony Fillion-Maillet

Fullstack geliştirici, SharpSkill kurucusu

10 yılı aşkın süredir fullstack geliştirici. SharpSkill’i yönetiyor ve burada yayımlanan her şeyden sorumlu.

17 Ağustos 2026 tarihinde güncellendi

Paylaş

İlgili makaleler