{"id":34513,"date":"2025-11-18T02:40:53","date_gmt":"2025-11-17T23:40:53","guid":{"rendered":"https:\/\/fatihsoysal.com\/blog\/?p=34513"},"modified":"2025-11-18T02:40:53","modified_gmt":"2025-11-17T23:40:53","slug":"angularda-reactive-formlar-degisiklikleri-dinleme","status":"publish","type":"post","link":"https:\/\/fatihsoysal.com\/blog\/angularda-reactive-formlar-degisiklikleri-dinleme\/","title":{"rendered":"Angular&#8217;da Reactive Formlar: De\u011fi\u015fiklikleri Dinleme"},"content":{"rendered":"<p><body><\/p>\n<h2>Angular&#8217;da Reactive Formlar: De\u011fi\u015fiklikleri Dinleme<\/h2>\n<h2>Giri\u015f<\/h2>\n<p>Angular, modern web uygulamalar\u0131 geli\u015ftirmek i\u00e7in g\u00fc\u00e7l\u00fc ve esnek bir platform sunar. Bu platformun temel ta\u015flar\u0131ndan biri de form y\u00f6netimidir. Angular, formlar\u0131 y\u00f6netmek i\u00e7in iki farkl\u0131 yakla\u015f\u0131m sunar: Template-driven Forms ve Reactive Forms. Bu makalede, \u00f6zellikle b\u00fcy\u00fck \u00f6l\u00e7ekli ve karma\u015f\u0131k formlar i\u00e7in tercih edilen, daha \u00f6l\u00e7eklenebilir ve test edilebilir bir yap\u0131ya sahip olan Reactive Forms \u00fczerine odaklanaca\u011f\u0131z. Reactive Forms, form durumunu ve de\u011fi\u015fikliklerini programatik olarak y\u00f6netme imkan\u0131 sunar. Bu makalenin ana konusu ise, Reactive Forms yap\u0131s\u0131 i\u00e7inde form alanlar\u0131ndaki veya genel form durumundaki de\u011fi\u015fiklikleri nas\u0131l dinleyece\u011fimiz ve bu de\u011fi\u015fikliklere nas\u0131l tepki verece\u011fimizdir.<\/p>\n<p>Formlardaki de\u011fi\u015fiklikleri dinlemek, kullan\u0131c\u0131 deneyimini zenginle\u015ftirmek, veri b\u00fct\u00fcnl\u00fc\u011f\u00fcn\u00fc sa\u011flamak ve uygulaman\u0131n performans\u0131n\u0131 optimize etmek i\u00e7in kritik \u00f6neme sahiptir. \u00d6rne\u011fin, bir kullan\u0131c\u0131n\u0131n belirli bir alana giri\u015f yapmas\u0131yla ba\u015fka bir alan\u0131n g\u00f6r\u00fcn\u00fcrl\u00fc\u011f\u00fcn\u00fc de\u011fi\u015ftirebilir, formun ge\u00e7erlili\u011fine g\u00f6re bir g\u00f6nder d\u00fc\u011fmesini etkinle\u015ftirebilir veya belirli bir gecikmeyle sunucuya otomatik arama istekleri g\u00f6nderebilirsiniz. T\u00fcm bu senaryolar, Reactive Forms&#8217;un sundu\u011fu g\u00fc\u00e7l\u00fc g\u00f6zlemlenebilir (observable) mekanizmalar\u0131 sayesinde kolayca uygulanabilir.<\/p>\n<p>Bu makalede, <code>FormControl<\/code>, <code>FormGroup<\/code> ve <code>FormArray<\/code> gibi Reactive Forms yap\u0131lar\u0131n\u0131 kullanarak <code>valueChanges<\/code> ve <code>statusChanges<\/code> g\u00f6zlemlenebilirlerini derinlemesine inceleyece\u011fiz. Ayr\u0131ca, RxJS operat\u00f6rlerini (\u00f6rne\u011fin <code>debounceTime<\/code>, <code>distinctUntilChanged<\/code>, <code>switchMap<\/code>) kullanarak bu de\u011fi\u015fiklikleri nas\u0131l daha etkin bir \u015fekilde y\u00f6netece\u011fimizi, performans sorunlar\u0131n\u0131 nas\u0131l \u00e7\u00f6zece\u011fimizi ve \u00e7e\u015fitli pratik senaryolar\u0131 nas\u0131l uygulayaca\u011f\u0131m\u0131z\u0131 \u00f6\u011frenece\u011fiz. Son olarak, bellek s\u0131z\u0131nt\u0131lar\u0131n\u0131 \u00f6nlemek i\u00e7in abonelikleri do\u011fru bir \u015fekilde y\u00f6netmenin \u00f6nemine de\u011finece\u011fiz.<\/p>\n<h2>Reactive Form Temelleri ve De\u011fi\u015fiklik Dinleme Mekanizmalar\u0131<\/h2>\n<p>Angular Reactive Forms, form kontrollerini programatik olarak olu\u015fturman\u0131za ve y\u00f6netmenize olanak tan\u0131r. Formun her bir par\u00e7as\u0131 bir JavaScript s\u0131n\u0131f\u0131 taraf\u0131ndan temsil edilir ve bu s\u0131n\u0131flar formun de\u011ferini ve durumunu bir g\u00f6zlemlenebilir ak\u0131\u015f (observable stream) olarak sunar.<\/p>\n<h3><code>FormControl<\/code>, <code>FormGroup<\/code>, <code>FormArray<\/code> Yap\u0131lar\u0131<\/h3>\n<p>Reactive Forms&#8217;un \u00fc\u00e7 temel yap\u0131 ta\u015f\u0131 vard\u0131r:<br \/>\n*   <strong><code>FormControl<\/code><\/strong>: Tek bir form giri\u015f alan\u0131n\u0131 (input, select, textarea vb.) temsil eder. De\u011ferini, ge\u00e7erlili\u011fini ve durumunu y\u00f6netir.<br \/>\n*   <strong><code>FormGroup<\/code><\/strong>: Bir grup <code>FormControl<\/code> veya ba\u015fka <code>FormGroup<\/code> \u00f6rneklerini bir araya getirir. Genellikle bir formun tamam\u0131n\u0131 veya mant\u0131ksal olarak ili\u015fkili bir b\u00f6l\u00fcm\u00fcn\u00fc temsil eder. T\u00fcm alt kontrollerinin de\u011ferlerini ve ge\u00e7erlilik durumunu toplar.<br \/>\n*   <strong><code>FormArray<\/code><\/strong>: Dinamik olarak eklenip \u00e7\u0131kar\u0131labilen bir kontrol koleksiyonunu temsil eder. \u00d6rne\u011fin, bir kullan\u0131c\u0131n\u0131n birden fazla e-posta adresi veya telefon numaras\u0131 girebildi\u011fi senaryolarda kullan\u0131\u015fl\u0131d\u0131r.<\/p>\n<p>Bu \u00fc\u00e7 s\u0131n\u0131f\u0131n her biri, formdaki de\u011fi\u015fiklikleri dinlemek i\u00e7in iki \u00f6nemli g\u00f6zlemlenebilir (observable) \u00f6zellik sunar: <code>valueChanges<\/code> ve <code>statusChanges<\/code>.<\/p>\n<h3><code>valueChanges<\/code> Observable&#8217;\u0131<\/h3>\n<p><code>valueChanges<\/code>, bir <code>FormControl<\/code>, <code>FormGroup<\/code> veya <code>FormArray<\/code>&#8216;\u0131n de\u011feri her de\u011fi\u015fti\u011finde yeni bir de\u011fer yayan bir RxJS Observable&#8217;\u0131d\u0131r. Bu, kullan\u0131c\u0131n\u0131n form alanlar\u0131na her giri\u015f yapt\u0131\u011f\u0131nda, programatik olarak bir de\u011fer atand\u0131\u011f\u0131nda veya form s\u0131f\u0131rland\u0131\u011f\u0131nda tetiklenir.<\/p>\n<h4><code>FormControl<\/code> ile Kullan\u0131m\u0131<\/h4>\n<p>Tek bir giri\u015f alan\u0131n\u0131n de\u011ferindeki de\u011fi\u015fiklikleri izlemek i\u00e7in <code>FormControl<\/code>&#8216;un <code>valueChanges<\/code> \u00f6zelli\u011fini kullan\u0131r\u0131z.<\/p>\n<pre><code class=\"language-typescript\">import { Component, OnInit, OnDestroy } from '@angular\/core';\nimport { FormControl } from '@angular\/forms';\nimport { Subject } from 'rxjs';\nimport { takeUntil } from 'rxjs\/operators';\n\n@Component({\n  selector: 'app-search-input',\n  template: <code>\n    <input type=\"text\" [formControl]=\"searchControl\" placeholder=\"Ara...\">\n    <p>Arama Terimi: {{ searchTerm }}<\/p>\n  <\/code>\n})\nexport class SearchInputComponent implements OnInit, OnDestroy {\n  searchControl = new FormControl('');\n  searchTerm: string = '';\n  private destroy$ = new Subject<void>();\n\n  ngOnInit() {\n    this.searchControl.valueChanges\n      .pipe(\n        takeUntil(this.destroy$) \/\/ Bellek s\u0131z\u0131nt\u0131s\u0131n\u0131 \u00f6nlemek i\u00e7in\n      )\n      .subscribe(value => {\n        this.searchTerm = value;\n        console.log('Arama terimi de\u011fi\u015fti:', value);\n        \/\/ Burada arama i\u015flemini tetikleyebilirsiniz\n      });\n  }\n\n  ngOnDestroy() {\n    this.destroy$.next();\n    this.destroy$.complete();\n  }\n}<\/code><\/pre>\n<p>Yukar\u0131daki \u00f6rnekte, <code>searchControl<\/code> adl\u0131 <code>FormControl<\/code>&#8216;un de\u011feri her de\u011fi\u015fti\u011finde, <code>subscribe<\/code> blo\u011fu i\u00e7indeki kod \u00e7al\u0131\u015f\u0131r. Bu sayede, kullan\u0131c\u0131n\u0131n yazd\u0131\u011f\u0131 her karakterde <code>searchTerm<\/code> de\u011fi\u015fkeni g\u00fcncellenir ve konsola loglan\u0131r.<\/p>\n<h4><code>FormGroup<\/code> ile Kullan\u0131m\u0131<\/h4>\n<p>Bir <code>FormGroup<\/code>&#8216;un <code>valueChanges<\/code> \u00f6zelli\u011fi, gruptaki herhangi bir kontrol\u00fcn de\u011feri de\u011fi\u015fti\u011finde tetiklenir ve <code>FormGroup<\/code>&#8216;un t\u00fcm de\u011ferlerini i\u00e7eren bir nesne yay\u0131mlar. Bu, formun genel de\u011ferini izlemek i\u00e7in idealdir.<\/p>\n<pre><code class=\"language-typescript\">import { Component, OnInit, OnDestroy } from '@angular\/core';\nimport { FormGroup, FormControl, Validators } from '@angular\/forms';\nimport { Subject } from 'rxjs';\nimport { takeUntil } from 'rxjs\/operators';\n\n@Component({\n  selector: 'app-user-profile',\n  template: <code>\n    <form [formGroup]=\"userProfileForm\">\n      <input type=\"text\" formControlName=\"firstName\" placeholder=\"Ad\">\n      <input type=\"text\" formControlName=\"lastName\" placeholder=\"Soyad\">\n      <input type=\"email\" formControlName=\"email\" placeholder=\"E-posta\">\n    <\/form>\n    <pre>{{ formValues | json }}<\/pre>\n<p>  <\/code><br \/>\n})<br \/>\nexport class UserProfileComponent implements OnInit, OnDestroy {<br \/>\n  userProfileForm = new FormGroup({<br \/>\n    firstName: new FormControl('', Validators.required),<br \/>\n    lastName: new FormControl('', Validators.required),<br \/>\n    email: new FormControl('', [Validators.required, Validators.email])<br \/>\n  });<\/p>\n<p>  formValues: any;<br \/>\n  private destroy$ = new Subject<void>();<\/p>\n<p>  ngOnInit() {<br \/>\n    this.userProfileForm.valueChanges<br \/>\n      .pipe(<br \/>\n        takeUntil(this.destroy$)<br \/>\n      )<br \/>\n      .subscribe(values => {<br \/>\n        this.formValues = values;<br \/>\n        console.log('Form de\u011ferleri de\u011fi\u015fti:', values);<br \/>\n        \/\/ Burada formun tamam\u0131n\u0131n de\u011ferine g\u00f6re i\u015flemler yapabilirsiniz<br \/>\n      });<br \/>\n  }<\/p>\n<p>  ngOnDestroy() {<br \/>\n    this.destroy$.next();<br \/>\n    this.destroy$.complete();<br \/>\n  }<br \/>\n}<\/code><br \/>\nBu \u00f6rnekte, <code>userProfileForm<\/code> i\u00e7indeki <code>firstName<\/code>, <code>lastName<\/code> veya <code>email<\/code> alanlar\u0131ndan herhangi biri de\u011fi\u015fti\u011finde, <code>userProfileForm.valueChanges<\/code> tetiklenir ve t\u00fcm formun g\u00fcncel de\u011ferini (<code>{ firstName: '...', lastName: '...', email: '...' }<\/code> \u015feklinde) yay\u0131mlar.<\/p>\n<h4><code>FormArray<\/code> ile Kullan\u0131m\u0131<\/h4>\n<p><code>FormArray<\/code>&#8216;\u0131n <code>valueChanges<\/code> \u00f6zelli\u011fi, dizideki herhangi bir kontrol\u00fcn de\u011feri de\u011fi\u015fti\u011finde veya diziye yeni bir kontrol eklendi\u011finde\/\u00e7\u0131kar\u0131ld\u0131\u011f\u0131nda tetiklenir. Yay\u0131mlanan de\u011fer, dizideki t\u00fcm kontrollerin de\u011ferlerini i\u00e7eren bir dizidir.<\/p>\n<pre><code class=\"language-typescript\">import { Component, OnInit, OnDestroy } from '@angular\/core';\nimport { FormArray, FormControl, FormGroup, Validators, FormBuilder } from '@angular\/forms';\nimport { Subject } from 'rxjs';\nimport { takeUntil } from 'rxjs\/operators';\n\n@Component({\n  selector: 'app-skill-list',\n  template: <code>\n    <form [formGroup]=\"skillForm\">\n      <div formArrayName=\"skills\">\n        <div *ngFor=\"let skill of skills.controls; let i = index\">\n          <input type=\"text\" [formControlName]=\"i\" placeholder=\"Yetenek {{i+1}}\">\n          <button type=\"button\" (click)=\"removeSkill(i)\">Kald\u0131r<\/button>\n        <\/div>\n      <\/div>\n      <button type=\"button\" (click)=\"addSkill()\">Yetenek Ekle<\/button>\n    <\/form>\n    <pre>{{ skillForm.value | json }}<\/pre>\n<p>  <\/code><br \/>\n})<br \/>\nexport class SkillListComponent implements OnInit, OnDestroy {<br \/>\n  skillForm: FormGroup;<br \/>\n  private destroy$ = new Subject<void>();<\/p>\n<p>  constructor(private fb: FormBuilder) {<br \/>\n    this.skillForm = this.fb.group({<br \/>\n      skills: this.fb.array([this.fb.control('', Validators.required)])<br \/>\n    });<br \/>\n  }<\/p>\n<p>  get skills() {<br \/>\n    return this.skillForm.get('skills') as FormArray;<br \/>\n  }<\/p>\n<p>  addSkill() {<br \/>\n    this.skills.push(this.fb.control('', Validators.required));<br \/>\n  }<\/p>\n<p>  removeSkill(index: number) {<br \/>\n    this.skills.removeAt(index);<br \/>\n  }<\/p>\n<p>  ngOnInit() {<br \/>\n    this.skills.valueChanges<br \/>\n      .pipe(<br \/>\n        takeUntil(this.destroy$)<br \/>\n      )<br \/>\n      .subscribe(values => {<br \/>\n        console.log('Yetenekler de\u011fi\u015fti:', values);<br \/>\n        \/\/ Burada yetenekler dizisine g\u00f6re i\u015flemler yapabilirsiniz<br \/>\n      });<br \/>\n  }<\/p>\n<p>  ngOnDestroy() {<br \/>\n    this.destroy$.next();<br \/>\n    this.destroy$.complete();<br \/>\n  }<br \/>\n}<\/code><br \/>\nBu \u00f6rnekte, <code>skills<\/code> adl\u0131 <code>FormArray<\/code>&#8216;e yeni bir yetenek eklendi\u011finde, var olan bir yetenek kald\u0131r\u0131ld\u0131\u011f\u0131nda veya herhangi bir yetenek alan\u0131n\u0131n de\u011feri de\u011fi\u015fti\u011finde <code>skills.valueChanges<\/code> tetiklenir ve g\u00fcncel yetenekler dizisini yay\u0131mlar.<\/p>\n<h3><code>statusChanges<\/code> Observable&#8217;\u0131<\/h3>\n<p><code>statusChanges<\/code>, bir <code>FormControl<\/code>, <code>FormGroup<\/code> veya <code>FormArray<\/code>&#8216;\u0131n ge\u00e7erlilik durumu (validation status) her de\u011fi\u015fti\u011finde yeni bir durum yayan bir RxJS Observable&#8217;\u0131d\u0131r. Olas\u0131 durumlar \u015funlard\u0131r:<br \/>\n*   <strong>VALID<\/strong>: Kontrol veya grup ge\u00e7erlidir.<br \/>\n*   <strong>INVALID<\/strong>: Kontrol veya grup ge\u00e7ersizdir.<br \/>\n*   <strong>PENDING<\/strong>: Asenkron do\u011frulama devam etmektedir.<br \/>\n*   <strong>DISABLED<\/strong>: Kontrol veya grup devre d\u0131\u015f\u0131d\u0131r.<\/p>\n<h4>Kullan\u0131m Alanlar\u0131 ve \u00d6rnek Kod<\/h4>\n<p><code>statusChanges<\/code>, formun genel ge\u00e7erlili\u011fini izlemek ve buna g\u00f6re UI elementlerini (\u00f6rne\u011fin, bir g\u00f6nder d\u00fc\u011fmesini etkinle\u015ftirmek veya devre d\u0131\u015f\u0131 b\u0131rakmak) g\u00fcncellemek i\u00e7in \u00e7ok kullan\u0131\u015fl\u0131d\u0131r.<\/p>\n<pre><code class=\"language-typescript\">import { Component, OnInit, OnDestroy } from '@angular\/core';\nimport { FormGroup, FormControl, Validators } from '@angular\/forms';\nimport { Subject } from 'rxjs';\nimport { takeUntil } from 'rxjs\/operators';\n\n@Component({\n  selector: 'app-registration-form',\n  template: <code>\n    <form [formGroup]=\"registrationForm\">\n      <input type=\"text\" formControlName=\"username\" placeholder=\"Kullan\u0131c\u0131 Ad\u0131\">\n      <div *ngIf=\"registrationForm.get('username')?.invalid &#038;&#038; registrationForm.get('username')?.touched\">\n        Kullan\u0131c\u0131 ad\u0131 gerekli!\n      <\/div>\n      <input type=\"password\" formControlName=\"password\" placeholder=\"\u015eifre\">\n      <div *ngIf=\"registrationForm.get('password')?.invalid &#038;&#038; registrationForm.get('password')?.touched\">\n        \u015eifre en az 6 karakter olmal\u0131!\n      <\/div>\n      <button type=\"submit\" [disabled]=\"registrationForm.invalid\">Kaydol<\/button>\n    <\/form>\n    <p>Form Durumu: {{ formStatus }}<\/p>\n  <\/code>\n})\nexport class RegistrationFormComponent implements OnInit, OnDestroy {\n  registrationForm = new FormGroup({\n    username: new FormControl('', Validators.required),\n    password: new FormControl('', [Validators.required, Validators.minLength(6)])\n  });\n\n  formStatus: string = '';\n  private destroy$ = new Subject<void>();\n\n  ngOnInit() {\n    this.registrationForm.statusChanges\n      .pipe(\n        takeUntil(this.destroy$)\n      )\n      .subscribe(status => {\n        this.formStatus = status;\n        console.log('Form durumu de\u011fi\u015fti:', status);\n        \/\/ \u00d6rne\u011fin, form ge\u00e7erliyse bir API \u00e7a\u011fr\u0131s\u0131 yapabilirsiniz\n      });\n  }\n\n  ngOnDestroy() {\n    this.destroy$.next();\n    this.destroy$.complete();\n  }\n}<\/code><\/pre>\n<p>Bu \u00f6rnekte, <code>username<\/code> veya <code>password<\/code> alanlar\u0131n\u0131n ge\u00e7erlilik durumu de\u011fi\u015fti\u011finde (<code>VALID<\/code>, <code>INVALID<\/code>, <code>PENDING<\/code> gibi), <code>registrationForm.statusChanges<\/code> tetiklenir. Bu sayede <code>formStatus<\/code> de\u011fi\u015fkenini g\u00fcncelleyebilir ve &#8220;Kaydol&#8221; d\u00fc\u011fmesini formun genel ge\u00e7erlilik durumuna g\u00f6re etkinle\u015ftirebilir veya devre d\u0131\u015f\u0131 b\u0131rakabiliriz.<\/p>\n<h2>RxJS Operat\u00f6rleri ile De\u011fi\u015fiklikleri Y\u00f6netme<\/h2>\n<p><code>valueChanges<\/code> ve <code>statusChanges<\/code> g\u00f6zlemlenebilirleri, RxJS k\u00fct\u00fcphanesinin bir par\u00e7as\u0131d\u0131r. Bu, bize RxJS&#8217;in zengin operat\u00f6r setini kullanarak bu ak\u0131\u015flar\u0131 d\u00f6n\u00fc\u015ft\u00fcrme, filtreleme ve y\u00f6netme yetene\u011fi verir. Bu operat\u00f6rler, performans\u0131 art\u0131rmak, gereksiz i\u015flemleri engellemek ve daha karma\u015f\u0131k mant\u0131klar\u0131 uygulamak i\u00e7in kritik \u00f6neme sahiptir.<\/p>\n<h3><code>debounceTime<\/code><\/h3>\n<p><code>debounceTime<\/code> operat\u00f6r\u00fc, bir Observable&#8217;\u0131n yay\u0131mlad\u0131\u011f\u0131 de\u011ferleri belirli bir s\u00fcre boyunca bekletir ve yaln\u0131zca o s\u00fcre i\u00e7inde ba\u015fka bir de\u011fer yay\u0131mlanmazsa son de\u011feri iletir. Bu, \u00f6zellikle kullan\u0131c\u0131n\u0131n h\u0131zl\u0131 bir \u015fekilde giri\u015f yapt\u0131\u011f\u0131 arama kutular\u0131 gibi durumlarda, her tu\u015f vuru\u015funda bir i\u015flem (\u00f6rne\u011fin API \u00e7a\u011fr\u0131s\u0131) tetiklemek yerine, kullan\u0131c\u0131n\u0131n yazmay\u0131 bitirmesini beklemek i\u00e7in \u00e7ok faydal\u0131d\u0131r. Performans\u0131 art\u0131r\u0131r ve sunucuya gereksiz istekleri azalt\u0131r.<\/p>\n<pre><code class=\"language-typescript\">import { Component, OnInit, OnDestroy } from '@angular\/core';\nimport { FormControl } from '@angular\/forms';\nimport { Subject } from 'rxjs';\nimport { debounceTime, distinctUntilChanged, takeUntil } from 'rxjs\/operators';\n\n@Component({\n  selector: 'app-debounced-search',\n  template: <code>\n    <input type=\"text\" [formControl]=\"searchControl\" placeholder=\"Arama yap...\">\n    <p>Son Arama: {{ lastSearchedTerm }}<\/p>\n  <\/code>\n})\nexport class DebouncedSearchComponent implements OnInit, OnDestroy {\n  searchControl = new FormControl('');\n  lastSearchedTerm: string = '';\n  private destroy$ = new Subject<void>();\n\n  ngOnInit() {\n    this.searchControl.valueChanges\n      .pipe(\n        debounceTime(300), \/\/ 300 ms i\u00e7inde ba\u015fka bir de\u011fer gelmezse tetikle\n        distinctUntilChanged(), \/\/ Sadece de\u011fer ger\u00e7ekten de\u011fi\u015ftiyse tetikle\n        takeUntil(this.destroy$)\n      )\n      .subscribe(value => {\n        this.lastSearchedTerm = value;\n        console.log('Debounce edilmi\u015f arama:', value);\n        \/\/ Burada API'ye arama iste\u011fi g\u00f6nderebilirsiniz\n      });\n  }\n\n  ngOnDestroy() {\n    this.destroy$.next();\n    this.destroy$.complete();\n  }\n}<\/code><\/pre>\n<p>Bu \u00f6rnekte, kullan\u0131c\u0131 <code>searchControl<\/code>&#8216;a her karakter yazd\u0131\u011f\u0131nda <code>valueChanges<\/code> tetiklenir, ancak <code>debounceTime(300)<\/code> sayesinde, kullan\u0131c\u0131 yazmay\u0131 b\u0131rakt\u0131ktan 300 milisaniye sonra de\u011fer <code>subscribe<\/code> blo\u011funa ula\u015f\u0131r. <code>distinctUntilChanged()<\/code> ise, ayn\u0131 de\u011ferin art arda gelmesini engeller (\u00f6rne\u011fin, &#8220;elma&#8221; yaz\u0131p geri silip tekrar &#8220;elma&#8221; yazmak gibi).<\/p>\n<h3><code>distinctUntilChanged<\/code><\/h3>\n<p><code>distinctUntilChanged<\/code> operat\u00f6r\u00fc, bir Observable&#8217;dan yay\u0131mlanan ard\u0131\u015f\u0131k ayn\u0131 de\u011ferleri filtreler. Yaln\u0131zca yeni yay\u0131mlanan de\u011fer bir \u00f6nceki de\u011ferden farkl\u0131ysa bu de\u011feri iletir. Bu, bir de\u011ferin de\u011fi\u015fti\u011fini ancak ayn\u0131 kald\u0131\u011f\u0131n\u0131 bildiren gereksiz tetiklemeleri \u00f6nlemek i\u00e7in kullan\u0131\u015fl\u0131d\u0131r.<\/p>\n<p>Yukar\u0131daki <code>debounceTime<\/code> \u00f6rne\u011finde oldu\u011fu gibi, <code>distinctUntilChanged<\/code> genellikle <code>debounceTime<\/code> ile birlikte kullan\u0131l\u0131r. Bu kombinasyon, \u00f6zellikle arama kutular\u0131 veya otomatik kaydetme i\u015flevleri i\u00e7in \u00e7ok etkilidir.<\/p>\n<h3><code>filter<\/code>, <code>map<\/code>, <code>switchMap<\/code> ve Di\u011ferleri<\/h3>\n<p>RxJS operat\u00f6rleri, Observable ak\u0131\u015flar\u0131n\u0131 manip\u00fcle etmek i\u00e7in \u00e7ok g\u00fc\u00e7l\u00fcd\u00fcr.<br \/>\n*   <strong><code>filter<\/code><\/strong>: Belirli bir ko\u015fulu kar\u015f\u0131lamayan de\u011ferleri ak\u0131\u015ftan \u00e7\u0131kar\u0131r. \u00d6rne\u011fin, sadece belirli bir uzunlu\u011fun \u00fczerindeki arama terimlerini i\u015flemek isteyebilirsiniz.<br \/>\n*   <strong><code>map<\/code><\/strong>: Her de\u011feri d\u00f6n\u00fc\u015ft\u00fcr\u00fcr ve d\u00f6n\u00fc\u015ft\u00fcr\u00fclm\u00fc\u015f de\u011feri yay\u0131mlar. \u00d6rne\u011fin, bir form grubunun de\u011ferini al\u0131p sadece belirli alanlar\u0131n\u0131 i\u00e7eren yeni bir nesne d\u00f6nd\u00fcrebilirsiniz.<br \/>\n*   <strong><code>switchMap<\/code><\/strong>: \u0130\u00e7 i\u00e7e ge\u00e7mi\u015f Observable&#8217;larla \u00e7al\u0131\u015f\u0131rken kullan\u0131l\u0131r. Bir d\u0131\u015f Observable&#8217;dan yeni bir de\u011fer geldi\u011finde, \u00f6nceki i\u00e7 Observable aboneli\u011fini iptal eder ve yeni bir i\u00e7 Observable&#8217;a abone olur. Bu, \u00f6zellikle her form de\u011fi\u015fikli\u011finde bir API \u00e7a\u011fr\u0131s\u0131 yaparken \u00f6nceki bekleyen \u00e7a\u011fr\u0131lar\u0131 iptal etmek i\u00e7in kritik \u00f6neme sahiptir, b\u00f6ylece sadece en son API iste\u011finin sonucu kullan\u0131l\u0131r.<\/p>\n<h4>\u00d6rnek Senaryolar: <code>filter<\/code> ve <code>switchMap<\/code> ile Otomatik Arama<\/h4>\n<pre><code class=\"language-typescript\">import { Component, OnInit, OnDestroy } from '@angular\/core';\nimport { FormControl } from '@angular\/forms';\nimport { Subject, of } from 'rxjs';\nimport { debounceTime, distinctUntilChanged, filter, switchMap, takeUntil } from 'rxjs\/operators';\n\n\/\/ Sahte bir API servisi\nclass SearchService {\n  search(term: string) {\n    console.log(<code>API'ye istek g\u00f6nderildi: ${term}<\/code>);\n    return of(<code>Arama sonu\u00e7lar\u0131 i\u00e7in: ${term}<\/code>).pipe(debounceTime(500)); \/\/ API gecikmesini sim\u00fcle et\n  }\n}\n\n@Component({\n  selector: 'app-advanced-search',\n  template: <code>\n    <input type=\"text\" [formControl]=\"searchControl\" placeholder=\"\u00dcr\u00fcn Ara...\">\n    <p>Sonu\u00e7: {{ searchResult }}<\/p>\n  <\/code>,\n  providers: [SearchService]\n})\nexport class AdvancedSearchComponent implements OnInit, OnDestroy {\n  searchControl = new FormControl('');\n  searchResult: string = '';\n  private destroy$ = new Subject<void>();\n\n  constructor(private searchService: SearchService) {}\n\n  ngOnInit() {\n    this.searchControl.valueChanges\n      .pipe(\n        debounceTime(400), \/\/ Kullan\u0131c\u0131 yazmay\u0131 b\u0131rakt\u0131ktan 400ms bekle\n        distinctUntilChanged(), \/\/ Sadece de\u011fer de\u011fi\u015ftiyse devam et\n        filter(term => term.length >= 3 || term.length === 0), \/\/ Sadece 3+ karakter veya bo\u015f string i\u00e7in ara\n        switchMap(term => {\n          if (term.length === 0) {\n            return of(''); \/\/ Bo\u015f arama i\u00e7in bo\u015f sonu\u00e7 d\u00f6nd\u00fcr\n          }\n          return this.searchService.search(term); \/\/ API \u00e7a\u011fr\u0131s\u0131 yap\n        }),\n        takeUntil(this.destroy$)\n      )\n      .subscribe(result => {\n        this.searchResult = result;\n        console.log('Arama sonucu:', result);\n      });\n  }\n\n  ngOnDestroy() {\n    this.destroy$.next();\n    this.destroy$.complete();\n  }\n}<\/code><\/pre>\n<p>Bu geli\u015fmi\u015f arama \u00f6rne\u011fi, RxJS operat\u00f6rlerinin g\u00fcc\u00fcn\u00fc g\u00f6stermektedir:<br \/>\n1.  <code>debounceTime(400)<\/code>: Kullan\u0131c\u0131 yazmay\u0131 bitirene kadar bekler.<br \/>\n2.  <code>distinctUntilChanged()<\/code>: Ayn\u0131 arama terimi i\u00e7in tekrar arama yapmay\u0131 engeller.<br \/>\n3.  <code>filter(term => term.length >= 3 || term.length === 0)<\/code>: Sadece 3 veya daha fazla karakter girildi\u011finde veya arama kutusu tamamen bo\u015falt\u0131ld\u0131\u011f\u0131nda arama yapar. Bu, \u00e7ok k\u0131sa terimler i\u00e7in gereksiz API \u00e7a\u011fr\u0131lar\u0131n\u0131 \u00f6nler.<br \/>\n4.  <code>switchMap(term => ...)<\/code>: Her yeni arama terimi geldi\u011finde, \u00f6nceki bekleyen arama iste\u011fini iptal eder ve <code>searchService.search()<\/code> taraf\u0131ndan d\u00f6nd\u00fcr\u00fclen yeni Observable&#8217;a abone olur. Bu, kullan\u0131c\u0131n\u0131n h\u0131zl\u0131ca yazmas\u0131 durumunda eski, alakas\u0131z sonu\u00e7lar\u0131n gelmesini engeller.<\/p>\n<h2>Pratik Uygulamalar ve Senaryolar<\/h2>\n<p>Reactive Forms&#8217;un de\u011fi\u015fiklik dinleme yetenekleri, \u00e7e\u015fitli pratik senaryolarda uygulaman\u0131z\u0131n davran\u0131\u015f\u0131n\u0131 dinamik olarak kontrol etmenizi sa\u011flar.<\/p>\n<h3>Dinamik Alanlar\u0131 Y\u00f6netme<\/h3>\n<p>Bir form alan\u0131n\u0131n de\u011ferine g\u00f6re ba\u015fka bir form alan\u0131n\u0131n g\u00f6r\u00fcn\u00fcrl\u00fc\u011f\u00fcn\u00fc, etkinli\u011fini veya ge\u00e7erlili\u011fini de\u011fi\u015ftirmek yayg\u0131n bir gereksinimdir.<\/p>\n<h4>Bir Alan\u0131n De\u011ferine G\u00f6re Ba\u015fka Bir Alan\u0131 Etkinle\u015ftirme\/Devre D\u0131\u015f\u0131 B\u0131rakma<\/h4>\n<p>\u00d6rne\u011fin, &#8220;Fatura adresi teslimat adresiyle ayn\u0131 m\u0131?&#8221; \u015feklinde bir onay kutusu oldu\u011funda, bu kutu i\u015faretlendi\u011finde fatura adresi alanlar\u0131n\u0131 devre d\u0131\u015f\u0131 b\u0131rakmak isteyebilirsiniz.<\/p>\n<pre><code class=\"language-typescript\">import { Component, OnInit, OnDestroy } from '@angular\/core';\nimport { FormGroup, FormControl, FormBuilder, Validators } from '@angular\/forms';\nimport { Subject } from 'rxjs';\nimport { takeUntil } from 'rxjs\/operators';\n\n@Component({\n  selector: 'app-address-form',\n  template: <code>\n    <form [formGroup]=\"addressForm\">\n      <h3>Teslimat Adresi<\/h3>\n      <input type=\"text\" formControlName=\"deliveryAddress\" placeholder=\"Teslimat Adresi\">\n\n      <h3>Fatura Adresi<\/h3>\n      <input type=\"checkbox\" formControlName=\"sameAsDelivery\"> Teslimat adresiyle ayn\u0131\n      <br>\n      <input type=\"text\" formControlName=\"billingAddress\" placeholder=\"Fatura Adresi\">\n    <\/form>\n    <pre>{{ addressForm.value | json }}<\/pre>\n<p>  <\/code><br \/>\n})<br \/>\nexport class AddressFormComponent implements OnInit, OnDestroy {<br \/>\n  addressForm: FormGroup;<br \/>\n  private destroy$ = new Subject<void>();<\/p>\n<p>  constructor(private fb: FormBuilder) {<br \/>\n    this.addressForm = this.fb.group({<br \/>\n      deliveryAddress: ['', Validators.required],<br \/>\n      sameAsDelivery: [false],<br \/>\n      billingAddress: ['', Validators.required]<br \/>\n    });<br \/>\n  }<\/p>\n<p>  ngOnInit() {<br \/>\n    this.addressForm.get('sameAsDelivery')?.valueChanges<br \/>\n      .pipe(<br \/>\n        takeUntil(this.destroy$)<br \/>\n      )<br \/>\n      .subscribe(sameAsDelivery => {<br \/>\n        const billingAddressControl = this.addressForm.get('billingAddress');<br \/>\n        if (sameAsDelivery) {<br \/>\n          billingAddressControl?.disable();<br \/>\n          billingAddressControl?.setValue(this.addressForm.get('deliveryAddress')?.value);<br \/>\n        } else {<br \/>\n          billingAddressControl?.enable();<br \/>\n          billingAddressControl?.setValue(''); \/\/ Veya \u00f6nceki de\u011feri geri y\u00fckle<br \/>\n        }<br \/>\n      });<\/p>\n<p>    \/\/ Teslimat adresi de\u011fi\u015fti\u011finde fatura adresini g\u00fcncelle (e\u011fer ayn\u0131 ise)<br \/>\n    this.addressForm.get('deliveryAddress')?.valueChanges<br \/>\n      .pipe(<br \/>\n        takeUntil(this.destroy$)<br \/>\n      )<br \/>\n      .subscribe(deliveryAddress => {<br \/>\n        if (this.addressForm.get('sameAsDelivery')?.value) {<br \/>\n          this.addressForm.get('billingAddress')?.setValue(deliveryAddress);<br \/>\n        }<br \/>\n      });<br \/>\n  }<\/p>\n<p>  ngOnDestroy() {<br \/>\n    this.destroy$.next();<br \/>\n    this.destroy$.complete();<br \/>\n  }<br \/>\n}<\/code><br \/>\nBu \u00f6rnekte, <code>sameAsDelivery<\/code> onay kutusunun de\u011feri de\u011fi\u015fti\u011finde, <code>billingAddress<\/code> kontrol\u00fc etkinle\u015ftirilir veya devre d\u0131\u015f\u0131 b\u0131rak\u0131l\u0131r ve de\u011feri g\u00fcncellenir. Ayr\u0131ca, <code>deliveryAddress<\/code> de\u011fi\u015fti\u011finde ve <code>sameAsDelivery<\/code> i\u015faretliyse, <code>billingAddress<\/code> otomatik olarak g\u00fcncellenir.<\/p>\n<h3>\u00c7apraz Alan Do\u011frulamas\u0131 (Cross-Field Validation)<\/h3>\n<p>Birden fazla form alan\u0131n\u0131n de\u011ferlerinin birbirine ba\u011fl\u0131 oldu\u011fu do\u011frulama senaryolar\u0131nda, <code>FormGroup<\/code>&#8216;un <code>valueChanges<\/code> \u00f6zelli\u011fini veya \u00f6zel bir do\u011frulay\u0131c\u0131y\u0131 kullanabiliriz. \u00d6rne\u011fin, &#8220;\u015fifre&#8221; ve &#8220;\u015fifre tekrar\u0131&#8221; alanlar\u0131n\u0131n e\u015fle\u015fmesi gibi.<\/p>\n<pre><code class=\"language-typescript\">import { Component, OnInit, OnDestroy } from '@angular\/core';\nimport { FormGroup, FormControl, Validators, FormBuilder, AbstractControl, ValidatorFn } from '@angular\/forms';\nimport { Subject } from 'rxjs';\nimport { takeUntil } from 'rxjs\/operators';\n\n\/\/ Custom validator for password matching\nfunction passwordMatchValidator(controlName: string, matchingControlName: string): ValidatorFn {\n  return (formGroup: AbstractControl): { [key: string]: any } | null => {\n    const control = formGroup.get(controlName);\n    const matchingControl = formGroup.get(matchingControlName);\n\n    if (!control || !matchingControl) {\n      return null;\n    }\n\n    \/\/ set error on matchingControl if validation fails\n    if (matchingControl.errors && !matchingControl.errors['passwordMismatch']) {\n      return null;\n    }\n\n    if (control.value !== matchingControl.value) {\n      matchingControl.setErrors({ passwordMismatch: true });\n      return { passwordMismatch: true };\n    } else {\n      matchingControl.setErrors(null);\n      return null;\n    }\n  };\n}\n\n@Component({\n  selector: 'app-password-match',\n  template: <code>\n    <form [formGroup]=\"passwordForm\">\n      <input type=\"password\" formControlName=\"password\" placeholder=\"\u015eifre\">\n      <div *ngIf=\"passwordForm.get('password')?.invalid &#038;&#038; passwordForm.get('password')?.touched\">\n        \u015eifre gerekli!\n      <\/div>\n      <input type=\"password\" formControlName=\"confirmPassword\" placeholder=\"\u015eifre Tekrar\u0131\">\n      <div *ngIf=\"passwordForm.get('confirmPassword')?.errors?.['passwordMismatch'] &#038;&#038; passwordForm.get('confirmPassword')?.touched\">\n        \u015eifreler e\u015fle\u015fmiyor!\n      <\/div>\n      <button type=\"submit\" [disabled]=\"passwordForm.invalid\">G\u00f6nder<\/button>\n    <\/form>\n  <\/code>\n})\nexport class PasswordMatchComponent implements OnInit, OnDestroy {\n  passwordForm: FormGroup;\n  private destroy$ = new Subject<void>();\n\n  constructor(private fb: FormBuilder) {\n    this.passwordForm = this.fb.group({\n      password: ['', Validators.required],\n      confirmPassword: ['', Validators.required]\n    }, { validators: passwordMatchValidator('password', 'confirmPassword') });\n  }\n\n  ngOnInit() {\n    \/\/ \u015eifre alanlar\u0131ndan biri de\u011fi\u015fti\u011finde \u00e7apraz do\u011frulamay\u0131 tetiklemek i\u00e7in\n    \/\/ FormGroup seviyesindeki validator zaten bunu yapar, ancak manuel tetikleme gerekirse:\n    this.passwordForm.valueChanges\n      .pipe(\n        takeUntil(this.destroy$)\n      )\n      .subscribe(() => {\n        \/\/ Bu subscription, formdaki herhangi bir de\u011fer de\u011fi\u015fti\u011finde formGroup'un validator'\u0131n\u0131n\n        \/\/ tekrar \u00e7al\u0131\u015fmas\u0131n\u0131 sa\u011flar. Genellikle FormGroup seviyesindeki validatorlar\n        \/\/ de\u011fer de\u011fi\u015fti\u011finde otomatik olarak \u00e7al\u0131\u015f\u0131r, bu y\u00fczden bu \u00f6zel bir duruma gerek kalmayabilir.\n        \/\/ Ancak, karma\u015f\u0131k ba\u011f\u0131ml\u0131l\u0131klar varsa, manuel updateValueAndValidity() \u00e7a\u011fr\u0131s\u0131 gerekebilir.\n        \/\/ this.passwordForm.get('confirmPassword')?.updateValueAndValidity({ emitEvent: false });\n      });\n  }\n\n  ngOnDestroy() {\n    this.destroy$.next();\n    this.destroy$.complete();\n  }\n}<\/code><\/pre>\n<p>Bu \u00f6rnekte, <code>passwordMatchValidator<\/code> adl\u0131 \u00f6zel bir do\u011frulay\u0131c\u0131, <code>passwordForm<\/code>&#8216;a uygulan\u0131r. Bu do\u011frulay\u0131c\u0131, <code>password<\/code> ve <code>confirmPassword<\/code> alanlar\u0131n\u0131n de\u011ferlerini kar\u015f\u0131la\u015ft\u0131r\u0131r. Alanlardan biri de\u011fi\u015fti\u011finde, <code>FormGroup<\/code> seviyesindeki do\u011frulay\u0131c\u0131 tetiklenir ve \u015fifrelerin e\u015fle\u015fip e\u015fle\u015fmedi\u011fini kontrol eder.<\/p>\n<h3>Sunucuya Otomatik Kaydetme veya Arama<\/h3>\n<p>Daha \u00f6nce <code>debounceTime<\/code> ve <code>switchMap<\/code> ile g\u00f6sterilen arama \u00f6rne\u011fi, ayn\u0131 zamanda otomatik kaydetme i\u015flevleri i\u00e7in de kullan\u0131labilir. Kullan\u0131c\u0131 formdaki verileri de\u011fi\u015ftirdi\u011finde, belirli bir s\u00fcre (\u00f6rne\u011fin 1-2 saniye) beklendikten sonra, form verilerini otomatik olarak sunucuya g\u00f6nderebilirsiniz.<\/p>\n<pre><code class=\"language-typescript\">\/\/ \u00d6nceki AdvancedSearchComponent \u00f6rne\u011findeki mant\u0131k, SaveService ile uyarlanabilir.\n\/\/ searchService yerine saveService.save(formValue) \u00e7a\u011fr\u0131s\u0131 yap\u0131labilir.<\/code><\/pre>\n<h3>Form Durumunu \u0130zleme ve Kaydetme<\/h3>\n<p>Formun <code>dirty<\/code> (kirli &#8211; yani kullan\u0131c\u0131 taraf\u0131ndan de\u011fi\u015ftirilmi\u015f), <code>pristine<\/code> (temiz &#8211; ba\u015flang\u0131\u00e7 de\u011feriyle ayn\u0131), <code>valid<\/code> (ge\u00e7erli) veya <code>invalid<\/code> (ge\u00e7ersiz) gibi durumlar\u0131n\u0131 izlemek, kullan\u0131c\u0131ya geri bildirim sa\u011flamak veya formun kaydedilebilirli\u011fini kontrol etmek i\u00e7in \u00f6nemlidir. <code>statusChanges<\/code> ve <code>valueChanges<\/code> ile bu durumlar\u0131 kolayca takip edebilirsiniz.<\/p>\n<pre><code class=\"language-typescript\">\/\/ \u00d6nceki RegistrationFormComponent \u00f6rne\u011findeki gibi, statusChanges ile formun ge\u00e7erlili\u011fini izleyebiliriz.\n\/\/ Ayr\u0131ca, form.dirty veya form.pristine \u00f6zelliklerini de kontrol edebiliriz.<\/code><\/pre>\n<h2>Abonelikleri Y\u00f6netme ve Bellek S\u0131z\u0131nt\u0131lar\u0131n\u0131 \u00d6nleme<\/h2>\n<p>RxJS Observable&#8217;lar\u0131na abone oldu\u011funuzda, bu abonelikleri uygun bir \u015fekilde y\u00f6netmek ve bile\u015fen yok edildi\u011finde iptal etmek \u00e7ok \u00f6nemlidir. Aksi takdirde, abonelikler bellekte kalmaya devam eder ve bellek s\u0131z\u0131nt\u0131lar\u0131na yol a\u00e7ar, bu da uygulaman\u0131z\u0131n performans\u0131n\u0131 olumsuz etkiler.<\/p>\n<h3><code>unsubscribe()<\/code> Kullan\u0131m\u0131<\/h3>\n<p>Her <code>subscribe()<\/code> \u00e7a\u011fr\u0131s\u0131 bir <code>Subscription<\/code> nesnesi d\u00f6nd\u00fcr\u00fcr. Bu nesnenin <code>unsubscribe()<\/code> metodunu \u00e7a\u011f\u0131rarak aboneli\u011fi manuel olarak iptal edebilirsiniz.<\/p>\n<pre><code class=\"language-typescript\">import { Component, OnInit, OnDestroy } from '@angular\/core';\nimport { FormControl } from '@angular\/forms';\nimport { Subscription } from 'rxjs';\n\n@Component({\n  selector: 'app-manual-unsubscribe',\n  template: <code>\n    <input type=\"text\" [formControl]=\"myControl\">\n  <\/code>\n})\nexport class ManualUnsubscribeComponent implements OnInit, OnDestroy {\n  myControl = new FormControl('');\n  private mySubscription: Subscription | undefined;\n\n  ngOnInit() {\n    this.mySubscription = this.myControl.valueChanges.subscribe(value => {\n      console.log('De\u011fer:', value);\n    });\n  }\n\n  ngOnDestroy() {\n    if (this.mySubscription) {\n      this.mySubscription.unsubscribe();\n      console.log('Abonelik iptal edildi.');\n    }\n  }\n}<\/code><\/pre>\n<p>Birden fazla aboneli\u011finiz varsa, bunlar\u0131 bir <code>Subscription<\/code> dizisinde toplay\u0131p <code>ngOnDestroy<\/code> i\u00e7inde d\u00f6ng\u00fc ile iptal edebilirsiniz.<\/p>\n<h3><code>takeUntil<\/code> Operat\u00f6r\u00fc<\/h3>\n<p><code>takeUntil<\/code> operat\u00f6r\u00fc, bir Observable&#8217;\u0131n ba\u015fka bir Observable de\u011fer yay\u0131mlayana kadar de\u011ferleri yay\u0131mlamas\u0131n\u0131 sa\u011flar. Bu, abonelikleri y\u00f6netmek i\u00e7in daha temiz ve RxJS idiomatik bir yoldur. Genellikle, bile\u015fenin yok edildi\u011fini belirten bir <code>Subject<\/code> (genellikle <code>destroy$<\/code>) ile birlikte kullan\u0131l\u0131r.<\/p>\n<p>Yukar\u0131daki t\u00fcm \u00f6rneklerimizde <code>takeUntil(this.destroy$)<\/code> kullan\u0131m\u0131n\u0131 g\u00f6rebilirsiniz. Bu y\u00f6ntem, her bir aboneli\u011fi ayr\u0131 ayr\u0131 y\u00f6netmek yerine tek bir <code>Subject<\/code> ile t\u00fcm abonelikleri otomatik olarak iptal etmenizi sa\u011flar.<\/p>\n<pre><code class=\"language-typescript\">import { Component, OnInit, OnDestroy } from '@angular\/core';\nimport { FormControl } from '@angular\/forms';\nimport { Subject } from 'rxjs';\nimport { takeUntil } from 'rxjs\/operators';\n\n@Component({\n  selector: 'app-take-until-example',\n  template: <code>\n    <input type=\"text\" [formControl]=\"myControl\">\n  <\/code>\n})\nexport class TakeUntilExampleComponent implements OnInit, OnDestroy {\n  myControl = new FormControl('');\n  private destroy$ = new Subject<void>(); \/\/ Bile\u015fenin yok edildi\u011fini bildiren Subject\n\n  ngOnInit() {\n    this.myControl.valueChanges\n      .pipe(\n        takeUntil(this.destroy$) \/\/ destroy$ bir de\u011fer yay\u0131mlad\u0131\u011f\u0131nda aboneli\u011fi iptal et\n      )\n      .subscribe(value => {\n        console.log('De\u011fer:', value);\n      });\n  }\n\n  ngOnDestroy() {\n    this.destroy$.next(); \/\/ destroy$ Subject'ine bir de\u011fer yay\u0131mlayarak takeUntil'i tetikle\n    this.destroy$.complete(); \/\/ Subject'i tamamla\n  }\n}<\/code><\/pre>\n<h3><code>async<\/code> Pipe<\/h3>\n<p><code>async<\/code> pipe, Angular \u015fablonlar\u0131nda Observable&#8217;lar\u0131 do\u011frudan kullanman\u0131za olanak tan\u0131r. <code>async<\/code> pipe, Observable&#8217;a otomatik olarak abone olur ve bile\u015fen yok edildi\u011finde aboneli\u011fi otomatik olarak iptal eder. Bu, \u015fablon i\u00e7inde tek bir de\u011fer g\u00f6sterimi i\u00e7in \u00e7ok kullan\u0131\u015fl\u0131d\u0131r ancak bir form kontrol\u00fcn\u00fcn <code>valueChanges<\/code>&#8216;\u0131n\u0131 dinleyip buna g\u00f6re karma\u015f\u0131k yan etkiler olu\u015fturmak i\u00e7in genellikle yeterli de\u011fildir. Daha \u00e7ok, Observable&#8217;dan gelen veriyi do\u011frudan DOM&#8217;a ba\u011flamak i\u00e7in tercih edilir.<\/p>\n<pre><code class=\"language-typescript\">\/\/ \u015eablon i\u00e7inde:\n\/\/ <p>Arama Terimi: {{ searchControl.valueChanges | async }}<\/p><\/code><\/pre>\n<p>Bu y\u00f6ntem, yukar\u0131da bahsetti\u011fimiz karma\u015f\u0131k mant\u0131klar (debounce, switchMap vb.) i\u00e7in do\u011frudan uygun olmasa da, basit de\u011fer g\u00f6sterimleri i\u00e7in bellek y\u00f6netimini kolayla\u015ft\u0131r\u0131r.<\/p>\n<h2>En \u0130yi Uygulamalar ve \u0130pu\u00e7lar\u0131<\/h2>\n<p>*   <strong>Abonelikleri Her Zaman Y\u00f6netin<\/strong>: Bellek s\u0131z\u0131nt\u0131lar\u0131n\u0131 \u00f6nlemek i\u00e7in <code>takeUntil<\/code> veya <code>unsubscribe()<\/code> kullanarak abonelikleri her zaman iptal edin.<br \/>\n*   <strong>RxJS Operat\u00f6rlerini Ak\u0131ll\u0131ca Kullan\u0131n<\/strong>: <code>debounceTime<\/code> ve <code>distinctUntilChanged<\/code> gibi operat\u00f6rleri, \u00f6zellikle kullan\u0131c\u0131 giri\u015fine dayal\u0131 API \u00e7a\u011fr\u0131lar\u0131 yaparken performans\u0131 art\u0131rmak i\u00e7in kullan\u0131n.<br \/>\n*   <strong><code>switchMap<\/code> ile Yar\u0131\u015f Ko\u015fullar\u0131n\u0131 \u00d6nleyin<\/strong>: Bir \u00f6nceki Observable&#8217;\u0131n tamamlanmas\u0131ndan \u00f6nce yeni bir Observable olu\u015fturman\u0131z gerekti\u011finde (\u00f6rne\u011fin arama veya kaydetme API \u00e7a\u011fr\u0131lar\u0131), <code>switchMap<\/code> kullanarak yar\u0131\u015f ko\u015fullar\u0131n\u0131 ve eski verilerin i\u015flenmesini engelleyin.<br \/>\n*   <strong>Ayr\u0131 Form Gruplar\u0131 Olu\u015fturun<\/strong>: B\u00fcy\u00fck formlar\u0131 y\u00f6netmek i\u00e7in, formu mant\u0131ksal b\u00f6l\u00fcmlere ay\u0131r\u0131n ve her b\u00f6l\u00fcm i\u00e7in ayr\u0131 <code>FormGroup<\/code>&#8216;lar olu\u015fturun. Bu, kodu daha okunabilir ve y\u00f6netilebilir hale getirir.<br \/>\n*   <strong>Custom Validators Kullan\u0131n<\/strong>: Karma\u015f\u0131k do\u011frulama mant\u0131\u011f\u0131 i\u00e7in \u00f6zel do\u011frulay\u0131c\u0131lar yaz\u0131n. \u00c7apraz alan do\u011frulamas\u0131 i\u00e7in <code>FormGroup<\/code> seviyesinde do\u011frulay\u0131c\u0131lar kullan\u0131n.<br \/>\n*   <strong>Test Edilebilirli\u011fi G\u00f6z \u00d6n\u00fcnde Bulundurun<\/strong>: Reactive Forms, programatik yap\u0131s\u0131 sayesinde test edilebilirli\u011fi art\u0131r\u0131r. De\u011fi\u015fiklik dinleme mant\u0131\u011f\u0131n\u0131z\u0131 ayr\u0131 fonksiyonlara ay\u0131rarak veya do\u011frudan RxJS ak\u0131\u015flar\u0131n\u0131 test ederek kolayca test edebilirsiniz.<br \/>\n*   <strong>Performans\u0131 \u0130zleyin<\/strong>: A\u015f\u0131r\u0131 s\u0131k tetiklenen <code>valueChanges<\/code> abonelikleri uygulaman\u0131z\u0131n performans\u0131n\u0131 etkileyebilir. Geli\u015ftirici ara\u00e7lar\u0131n\u0131 kullanarak uygulaman\u0131z\u0131n performans\u0131n\u0131 izleyin ve gerekti\u011finde <code>debounceTime<\/code> gibi operat\u00f6rlerle optimizasyonlar yap\u0131n.<\/p>\n<h2>Sonu\u00e7<\/h2>\n<p>Angular Reactive Forms, form verilerini ve durumunu programatik olarak y\u00f6netmek i\u00e7in g\u00fc\u00e7l\u00fc ve esnek bir yap\u0131 sunar. <code>valueChanges<\/code> ve <code>statusChanges<\/code> g\u00f6zlemlenebilirleri, formdaki de\u011fi\u015fiklikleri dinlemek ve bu de\u011fi\u015fikliklere dinamik olarak tepki vermek i\u00e7in temel mekanizmalar\u0131 sa\u011flar. RxJS operat\u00f6rlerini bu g\u00f6zlemlenebilirlerle birle\u015ftirmek, form mant\u0131\u011f\u0131n\u0131 daha verimli, performansl\u0131 ve okunabilir hale getirir. <code>debounceTime<\/code>, <code>distinctUntilChanged<\/code>, <code>filter<\/code> ve <code>switchMap<\/code> gibi operat\u00f6rler sayesinde, kullan\u0131c\u0131 deneyimini iyile\u015ftiren ve uygulaman\u0131n kaynaklar\u0131n\u0131 daha verimli kullanan karma\u015f\u0131k senaryolar\u0131 kolayca uygulayabilirsiniz.<\/p>\n<p>Bellek s\u0131z\u0131nt\u0131lar\u0131n\u0131 \u00f6nlemek i\u00e7in abonelik y\u00f6netiminin (\u00f6zellikle <code>takeUntil<\/code> operat\u00f6r\u00fcyle) kritik \u00f6nemi unutulmamal\u0131d\u0131r. Do\u011fru uygulamalar ve en iyi pratiklerle, Angular Reactive Forms&#8217;u kullanarak hem g\u00fc\u00e7l\u00fc hem de s\u00fcrd\u00fcr\u00fclebilir form \u00e7\u00f6z\u00fcmleri geli\u015ftirebilirsiniz. Bu makale, Angular Reactive Forms&#8217;ta de\u011fi\u015fiklikleri dinleme konusunda kapsaml\u0131 bir rehber sunarak, geli\u015ftiricilerin daha dinamik ve etkile\u015fimli kullan\u0131c\u0131 aray\u00fczleri olu\u015fturmalar\u0131na yard\u0131mc\u0131 olmay\u0131 ama\u00e7lam\u0131\u015ft\u0131r.<\/body><\/p>\n","protected":false},"excerpt":{"rendered":"Angular&#8217;da Reactive Formlar: De\u011fi\u015fiklikleri Dinleme\nGiri\u015f\nAngular, modern web uygulamalar\u0131 geli\u015ftirmek i\u00e7in g\u00fc\u00e7l\u00fc ve esnek bir platform suna","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"csco_page_header_type":"","csco_page_load_nextpost":"","csco_page_subscribe_form":"","csco_page_contact_form":"","footnotes":""},"categories":[128],"tags":[],"class_list":{"0":"post-34513","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-react","7":"cs-entry","8":"cs-video-wrap"},"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v20.5 (Yoast SEO v25.3.1) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Angular&#039;da Reactive Formlar: De\u011fi\u015fiklikleri Dinleme - Kodlar\u0131n Gizemli D\u00fcnyas\u0131<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/fatihsoysal.com\/blog\/angularda-reactive-formlar-degisiklikleri-dinleme\/\" \/>\n<meta property=\"og:locale\" content=\"tr_TR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Angular&#039;da Reactive Formlar: De\u011fi\u015fiklikleri Dinleme\" \/>\n<meta property=\"og:description\" content=\"Angular&#039;da Reactive Formlar: De\u011fi\u015fiklikleri Dinleme Giri\u015f Angular, modern web uygulamalar\u0131 geli\u015ftirmek i\u00e7in g\u00fc\u00e7l\u00fc ve esnek bir platform suna\" \/>\n<meta property=\"og:url\" content=\"https:\/\/fatihsoysal.com\/blog\/angularda-reactive-formlar-degisiklikleri-dinleme\/\" \/>\n<meta property=\"og:site_name\" content=\"Kodlar\u0131n Gizemli D\u00fcnyas\u0131\" \/>\n<meta property=\"article:published_time\" content=\"2025-11-17T23:40:53+00:00\" \/>\n<meta name=\"author\" content=\"Fatih Soysal\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Yazan:\" \/>\n\t<meta name=\"twitter:data1\" content=\"Fatih Soysal\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tahmini okuma s\u00fcresi\" \/>\n\t<meta name=\"twitter:data2\" content=\"20 dakika\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/angularda-reactive-formlar-degisiklikleri-dinleme\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/angularda-reactive-formlar-degisiklikleri-dinleme\/\"},\"author\":{\"name\":\"Fatih Soysal\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"headline\":\"Angular&#8217;da Reactive Formlar: De\u011fi\u015fiklikleri Dinleme\",\"datePublished\":\"2025-11-17T23:40:53+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/angularda-reactive-formlar-degisiklikleri-dinleme\/\"},\"wordCount\":2772,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"articleSection\":[\"React\"],\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/fatihsoysal.com\/blog\/angularda-reactive-formlar-degisiklikleri-dinleme\/#respond\"]}],\"copyrightYear\":\"2025\",\"copyrightHolder\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/angularda-reactive-formlar-degisiklikleri-dinleme\/\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/angularda-reactive-formlar-degisiklikleri-dinleme\/\",\"name\":\"Angular'da Reactive Formlar: De\u011fi\u015fiklikleri Dinleme - Kodlar\u0131n Gizemli D\u00fcnyas\u0131\",\"isPartOf\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#website\"},\"datePublished\":\"2025-11-17T23:40:53+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/angularda-reactive-formlar-degisiklikleri-dinleme\/#breadcrumb\"},\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/fatihsoysal.com\/blog\/angularda-reactive-formlar-degisiklikleri-dinleme\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/angularda-reactive-formlar-degisiklikleri-dinleme\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Anasayfa\",\"item\":\"https:\/\/fatihsoysal.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Angular&#8217;da Reactive Formlar: De\u011fi\u015fiklikleri Dinleme\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#website\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/\",\"name\":\"Fatihsoysal.com\",\"description\":\"Blog - Yaz\u0131l\u0131m D\u00fcnyas\u0131 Tecr\u00fcbelerim\",\"publisher\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/fatihsoysal.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"tr\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\",\"name\":\"Fatih Soysal\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"tr\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png\",\"contentUrl\":\"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png\",\"width\":512,\"height\":512,\"caption\":\"Fatih Soysal\"},\"logo\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/\"},\"description\":\"Kullan\u0131m ve kodlama m\u00fckemmeliyetini odak alan uygulamalar olu\u015fturma deneyimine sahip, profesyonel olarak 15+ y\u0131l \u00fczeri deneyime sahip bir yaz\u0131l\u0131m m\u00fchendisi.\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/author\/fatihsoysal\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Angular'da Reactive Formlar: De\u011fi\u015fiklikleri Dinleme - Kodlar\u0131n Gizemli D\u00fcnyas\u0131","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/fatihsoysal.com\/blog\/angularda-reactive-formlar-degisiklikleri-dinleme\/","og_locale":"tr_TR","og_type":"article","og_title":"Angular'da Reactive Formlar: De\u011fi\u015fiklikleri Dinleme","og_description":"Angular'da Reactive Formlar: De\u011fi\u015fiklikleri Dinleme Giri\u015f Angular, modern web uygulamalar\u0131 geli\u015ftirmek i\u00e7in g\u00fc\u00e7l\u00fc ve esnek bir platform suna","og_url":"https:\/\/fatihsoysal.com\/blog\/angularda-reactive-formlar-degisiklikleri-dinleme\/","og_site_name":"Kodlar\u0131n Gizemli D\u00fcnyas\u0131","article_published_time":"2025-11-17T23:40:53+00:00","author":"Fatih Soysal","twitter_card":"summary_large_image","twitter_misc":{"Yazan:":"Fatih Soysal","Tahmini okuma s\u00fcresi":"20 dakika"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/fatihsoysal.com\/blog\/angularda-reactive-formlar-degisiklikleri-dinleme\/#article","isPartOf":{"@id":"https:\/\/fatihsoysal.com\/blog\/angularda-reactive-formlar-degisiklikleri-dinleme\/"},"author":{"name":"Fatih Soysal","@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"headline":"Angular&#8217;da Reactive Formlar: De\u011fi\u015fiklikleri Dinleme","datePublished":"2025-11-17T23:40:53+00:00","mainEntityOfPage":{"@id":"https:\/\/fatihsoysal.com\/blog\/angularda-reactive-formlar-degisiklikleri-dinleme\/"},"wordCount":2772,"commentCount":0,"publisher":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"articleSection":["React"],"inLanguage":"tr","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/fatihsoysal.com\/blog\/angularda-reactive-formlar-degisiklikleri-dinleme\/#respond"]}],"copyrightYear":"2025","copyrightHolder":{"@id":"https:\/\/fatihsoysal.com\/blog\/#organization"}},{"@type":"WebPage","@id":"https:\/\/fatihsoysal.com\/blog\/angularda-reactive-formlar-degisiklikleri-dinleme\/","url":"https:\/\/fatihsoysal.com\/blog\/angularda-reactive-formlar-degisiklikleri-dinleme\/","name":"Angular'da Reactive Formlar: De\u011fi\u015fiklikleri Dinleme - Kodlar\u0131n Gizemli D\u00fcnyas\u0131","isPartOf":{"@id":"https:\/\/fatihsoysal.com\/blog\/#website"},"datePublished":"2025-11-17T23:40:53+00:00","breadcrumb":{"@id":"https:\/\/fatihsoysal.com\/blog\/angularda-reactive-formlar-degisiklikleri-dinleme\/#breadcrumb"},"inLanguage":"tr","potentialAction":[{"@type":"ReadAction","target":["https:\/\/fatihsoysal.com\/blog\/angularda-reactive-formlar-degisiklikleri-dinleme\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/fatihsoysal.com\/blog\/angularda-reactive-formlar-degisiklikleri-dinleme\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Anasayfa","item":"https:\/\/fatihsoysal.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Angular&#8217;da Reactive Formlar: De\u011fi\u015fiklikleri Dinleme"}]},{"@type":"WebSite","@id":"https:\/\/fatihsoysal.com\/blog\/#website","url":"https:\/\/fatihsoysal.com\/blog\/","name":"Fatihsoysal.com","description":"Blog - Yaz\u0131l\u0131m D\u00fcnyas\u0131 Tecr\u00fcbelerim","publisher":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/fatihsoysal.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"tr"},{"@type":["Person","Organization"],"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1","name":"Fatih Soysal","image":{"@type":"ImageObject","inLanguage":"tr","@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png","contentUrl":"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png","width":512,"height":512,"caption":"Fatih Soysal"},"logo":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/"},"description":"Kullan\u0131m ve kodlama m\u00fckemmeliyetini odak alan uygulamalar olu\u015fturma deneyimine sahip, profesyonel olarak 15+ y\u0131l \u00fczeri deneyime sahip bir yaz\u0131l\u0131m m\u00fchendisi.","url":"https:\/\/fatihsoysal.com\/blog\/author\/fatihsoysal\/"}]}},"yoast_meta":{"yoast_wpseo_title":"","yoast_wpseo_metadesc":"","yoast_wpseo_canonical":""},"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/34513","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/comments?post=34513"}],"version-history":[{"count":1,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/34513\/revisions"}],"predecessor-version":[{"id":34514,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/34513\/revisions\/34514"}],"wp:attachment":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/media?parent=34513"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/categories?post=34513"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/tags?post=34513"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}