Angular ile(2 & 4) form kullanımı ve form doğrulama işlemleri( validations ) – Code Driven/Reactive Forms

Genel olarak tüm web uygulamalarımızda web form lar(sadece html form elementi içindeki yapı değil, kullanıcıdan veri girişi sağladığımız tüm kısımları düşünün ) uygulamalarımızın ana yapısını oluşturur. Angular 1.x deki form yapısı bir çokları gibi bana görede çok verimli ve esnek kullanımı olmayan bir yapıydı.

Angular 2 de  form kullanımı, Angular 1.x sürümlerine göre daha esnek ve birden fazla alternatifimiz var, fakat tıpkı angular 1 deki gibi Angular 2&4 ün de yine eleştirileceği bir alan diyebiliriz.

Angular  ile birlikte gelen yeni form alt yapısı genel olarak 3 şeyi kolaylaştırmayı hedeflemiş diyebilriz;  dinamik olarak formları daha kolay oluşturmak, formları daha kolay test edebilmek ve izolasyonu daha fazla ön plana çıkartmak.

Angular  ile birlikte form yapısınının temel parçalarını şu şekilde sıralayabiliriz.

  1. Controls,ControlGroup ve FormBuilder/ Form kontrolleri, grupları, ve form oluşturucu sınıflar
  2. Local variables / Yerel değişkenler
  3. Validations/Doğrulama işlemleri
  4. Dahili form direktifleri
  5. Observeables  / dinle ve tepki ver alt yapısı

Angular  içinde bir den farklı yöntemle formları oluşturup yönetebilmekteyiz.

1Template-driven(angular 1.x dekine benzer)

2-Code-driven/Reactive Forms(formu kod ile olusturmak))

Genelde bu farklı iki yapıdan ikincisini daha dinamik form yapıları  oluşturmak için (örneğin; form şeklini, yapısını, formdaki alanları sunucudan alıp formlari dinamik olarak oluşturmak gibi) yada form uzerinde Javascript le daha fazla kontrol sahibi olmak istedigimizde. İlkini ise(template-driven) statik daha basit yapılar için kullanımı düşünülmüş.

Bu yazıda, Code Driven modeline bakıp örneklerle anlamaya çalışacağız.  Bir sonraki yazi ilede Template Driven modele bakacağız.  Ayrıca, her hangi bir form yardımcısı kullanmadan [(ngModel)] veya local/yerel değişkenlerlede kullanıcıdan veri alma imkanımızın olmasından dolayı “Form alt yapısı disinda kalan”  kullanabilceğimiz diger seçeneklere de bakacağız.

Code-driven yapısıyla form işlemleri

Formlarımız üzerinde daha fazla kontrol ve daha dinamik bir yapı elde etmek istediğimiz de kullanışı bir yapı olan ve Code Driven / Kod temelli formlar diye isimlendirilen yapıya bakarak başlayalım.  Bu modelde, formlarımızı, Component içinde oluşturup html bağlantılarının otomatik olarak Angular tarafından yapıldığı “kod öncelikli” bir durum söz konusu.

Kısaca özetleyecek olursak, formdaki her bir input alanı için (textbox, select vs. ) bir FormControl nesnesi, sonra tüm bu Control leri kapsayan bir FormGroup nesnesine ihtiyacımız olacak. Sonrasında, FormGroup nesnesini kullanarak formun tümü üzerinde, FormControl nesnesini kullanarak da form içinde her bir elemente tek tek erişim ve kontrol imkanımız olacak.

Code Driven form yapısını daha iyi anlamak için bir “login/register” formu oluşturalım. Hızlı örnekleme için ben Angular CLI ile bir angular 4 projesi oluşturdum

ng new FormIslemleri

sonrasında, biri auth isimli, diğeri authForm isimli iki  component daha oluşturdum, bu componentlere  auth ve authForm ismi verip , login yada register diye isimlendirmemizin sebebi, tek bir component “AuthForm” dinamik olarak hem login hem de register işlemlerimize cevap verecek olması.  Böylece dinamik yapıya daha iyi bakma imkanımız olur .

ng g component auth

ng g component authForm

formlarımızın biraz daha düzgün gözükmesi için, src/index.html e bootstrap css kütüphanesini ekledim.

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" >

şimdi ilk olarak auth componentimizin, view kısmı oluşturalım , amacımız, Auth component içinde biri login diğeri  register işlemi için kullanacağımız iki componenti  render etmek, ama işin aslında, sadece bir componentimi zolacak ve durumu göre login yada register form olarak çalışabilecek. Auth componentimiz sadece üst seviye bir component içeri gayet sade ;

FormIslemleri\src\app\auth\auth.component.html

<div class="row">

    <div class="col-md-06">
      <app-auth-form></app-auth-form>
    </div>

    <div class="col-md-06">
      <app-auth-form></app-auth-form>
    </div>

</div>

Gördüğümüz gibi, auth componentimiz, içinde 2 tane auth-form componenti barındırmakta. Temel görevi formlarımıza bir üst yer tutucu olmak diyebiliriz. Şimdi auth-form componentimizin html tarafına geçelim. İhtiyacımız olan alanlar ,

Login içim

  • email
  • password

Register içn

  • email
  • password
  • password2(şifre tekrar)
  • isim

iki formumuzdada olacak ortak inputlar (email ve password)  a ek olarak, register formuna  ayrıyeten iki alan daha ekleyip kullanıcıdan , şifre tekrar ve isminide almak istemiş olduk. Şimdi formumuzun html tarafını hazırlayarak devam edelim.

src/app/auth-form/auth-form.component.html

<div class="col-md-12">
  <form>
    <div class="form-group">
      <label>Email</label>
      <input type="text" placeholder="email" class="form-control">
    </div>

    <div class="form-group">
      <label>Password</label>
      <input type="password" placeholder="******" class="form-control">
    </div>

    <div class="form-group">
      <label>Password Again</label>
      <input type="password" placeholder="******" class="form-control">
    </div>

    <div class="form-group">
      <label>Name</label>
      <input type="text" placeholder="name" class="form-control">
    </div>

    <button class="btn btn-sm btn-success">Giris veya Kayit</button>
  </form>
</div>

Son olarak, auth formun gözükmesi için, app-component e eklememiz yeterli olacak.

src/app/app.component.html

<h3>Angular ile form islemleri</h3>

<app-auth></app-auth>

Değişiklikleri kaydetip tarayıcıya baktığımızda, formlarımızın ilk haliyle ekrana yazdırıldığını görebiliriz.

 

Bir sonraki adım olarak, auth-formumuzu biraz daha akıllı hale getirip, login ve  register için doğru inputları gösterir hale getirelim. İlk olarak auth-forma bu işi daha kolay yapabilmesi için “formType” isimli bir input ekleyelim ve bu inputa göre formumuz düzgün bir şekilde (login veya register) olarak gözüksün. Ayrıca form başlığı ve formdaki button da da istediğimiz metinlerin gözükmesi için iki değişken tanımlayalım

src/app/auth-form/auth-form.component.ts

import {Component, Input, OnInit} from '@angular/core';

@Component({
  selector: 'app-auth-form',
  templateUrl: './auth-form.component.html',
  styleUrls: ['./auth-form.component.css']
})
export class AuthFormComponent implements OnInit {

  @Input('fromType') formType :String

  formTitle = 'Giris Yapin'
  buttonText='Giris'
  isLogin=true

  constructor() { }

  ngOnInit() {
    if(this.formType =='Register'){
      this.buttonText = 'Kayit';
      this.formTitle = 'Kayit Ol';
      this.isLogin = false;
    }
  }

}

componentdeki  bu değişiklikle, eğer formType olarak, “register” girişi alırsak, form daki başlık ve button daki text leri değiştirmiş olacağız. Eğer formType için her hangi bir değer tanımlanmazsa, varsayılan olarak formumuzun Login formu olduğunu kabul edeceğiz. Ayrıca, isLogin  değişkeni ile formdaki göstermek istediğimiz inputları koşullu olarak gösterebileceğiz.

formumuzun html tarafında da bir kaç değişikliğe ihtiyacımız var. isLogin değişkenine göre (eğer login form ise ) bazı inputların ekranda olmamamasi lazım. Html içinde *ngIf ile koşulu yönetebiliriz. Birde formumuzda title ve button text degerlerini dinamik hale getirecegiz.

src/app/auth-form/auth-form.component.html

 

<div class="col-md-12">
  <h3>{{formTitle}}</h3>
  <form>
    <div class="form-group">
      <label>Email</label>
      <input type="text" placeholder="email" class="form-control">
    </div>

    <div class="form-group">
      <label>Password</label>
      <input type="password" placeholder="******" class="form-control">
    </div>

    <div *ngIf="!isLogin" class="form-group">
      <label>Password Again</label>
      <input type="password" placeholder="******" class="form-control">
    </div>

    <div *ngIf="!isLogin" class="form-group">
      <label>Name</label>
      <input type="text" placeholder="name" class="form-control">
    </div>

    <button class="btn btn-sm btn-success">{{buttonText}}</button>
  </form>
</div>

password tekrari ve isim alanı artık sadece isLogin değişkeni false olduğunda ekrana yazdırılacak ayrıca, buttonText ve formTitle böylece dinamik hale gelmiş oldu. Bu haliyle değişiklikleri kaydedip tarayıcıya baktığımızda, iki tane Login form göreceğiz, formType olarak bir değer sağlamadığımız için varsayılan ayarlarımız devreye girmiş oldu.

Şimdi formlarımızdan birini Register  / Kayıt formuna dönüştürelim. Bunun için bir tanesine formType değeri sağlamamız yeterli olacak.

src/app/auth/auth.component.html

<div class="row">

    <div class="col-md-06">
      <app-auth-form></app-auth-form>
    </div>

    <div class="col-md-06">
      <app-auth-form [formType]="'Register'" ></app-auth-form>
    </div>

</div>

bu değişiklikle birlikte,

auth-form ilk dinamizmini kazanmış oldu, artık istediğimiz duruma göre aynı formu, login yada register olarak istediğimiz yerde kullanabiliriz. Şimdi, formumuzu angular form alt yapısını kullanabilecek duruma (Code Driven) getirelim. Bunun için ilk önce , formun tamamını temsil edecek bir “formGroup” a ve sonrasında her bir input için bir form controlle ihtiyacımız olacak. Ama register veya login işlemine göre yine iki control dinamik olarak tanımlanmak zorunda.

İlk olarak formGroup ve iki form içinde ortak olan email/password controllerini ve form üzerinde (giriş veya kayıt için) submit olayında kullancağımız bir metod u tanımlayarak başlayalım.

src/app/auth-form/auth-form.component.ts

import {Component, Input, OnInit} from '@angular/core';
import {FormControl, FormGroup} from "@angular/forms";

@Component({
  selector: 'app-auth-form',
  templateUrl: './auth-form.component.html',
  styleUrls: ['./auth-form.component.css']
})
export class AuthFormComponent implements OnInit {

  @Input('formType') formType :String

  formTitle = 'Giris Yapin'
  buttonText='Giris'
  isLogin=true

  emailCtrl = new FormControl('')
  passwordCtrl = new FormControl('')
  authForm : FormGroup

  constructor() { }

  ngOnInit() {
    if(this.formType =='Register'){
      this.buttonText = 'Kayit';
      this.formTitle = 'Kayit Ol';
      this.isLogin = false;
    }
  }

  private handleForm(){
    console.log(this.authForm.value)
  }

}

2 adet form control ve 1 adet form group değişkeni tanımladık. Bir de form gönderildiğinde formu işleyecek bir metod tanımladık ama daha çözmemiz gereken bir baız sorunlarımız var. Örneğin, component içinde bu örneklerin (FormGroup ve FormControl) html / view tarafında ki karşılıklarının da tanımlanması lazım.

Bu işlem için, Angular form modülü ile gelen iki direktif i kullanacağız. Ayrıca form daki submit olayınıda, ilgili metodumuza (handleForm) bağlamamız gerekmekte. Bu yüzden tekrar html tarafına dönelim ve ilgili değişiklikleri yapalım.

src/app/auth-form/auth-form.component.html

<div class="col-md-12">
  <h3>{{formTitle}}</h3>
  <form [formGroup]="authForm" (ngSubmit)="handleForm()">
    <div class="form-group">
      <label>Email</label>
      <input type="text" placeholder="email" class="form-control" formControlName="email">
    </div>

    <div class="form-group">
      <label>Password</label>
      <input type="password" placeholder="******" class="form-control" formControlName="password">
    </div>

    <div *ngIf="!isLogin" class="form-group">
      <label>Password Again</label>
      <input type="password" placeholder="******" class="form-control" formControlName="password2">
    </div>

    <div *ngIf="!isLogin" class="form-group">
      <label>Name</label>
      <input type="text" placeholder="name" class="form-control" formControlName="name">
    </div>

    <button type="submit" class="btn btn-sm btn-success">{{buttonText}}</button>
  </form>
</div>

Angular form modülü ile gelen formGroup direktifi ve formControlName direktfileri ile ilgili bağlantıyı yapmış olduk. artık formumuz group olarak authForm u temsil etmekte, ve ilgili controller de tek tek atanmış durumda. Ayrıca, (ngSubmit) eventi ile form işlemizin işleneceği metodu tanımlamış olduk. Bu arada formdaki butona daha önce eklemeyi unuttuğum html type ı (type=submit) ekledik. Böylece buton tıklandığında, submit olayı fırlatılacak ve (ngSubmit) ile belirttiğimiz handleForm metodu çağrılacak.

FromGroup ve Controller i component-html arasında ki ilişki açısından tanımlasakda, component tarafında hala işimiz var. Bir form gorup değişkenimiz olsada, henüz bir örneğini oluşturmadık. Bunun için component içinde, constructor metodumuzu kullanarak, form grubunu oluşturup ilgili controlleri bu gruba atayabiliriz.

src/app/auth-form/auth-form.component.ts

  constructor(private fb:FormBuilder) {
    this.authForm = fb.group({
      email:this.emailCtrl,
      password:this.passwordCtrl
    })
  }

burada dikkat etmememiz gereken husus, form grubumuzu oluştururken, sol tarafda html içinde formControlName direktifine atadığımız değerleri, sağ tarafta ise, component içindeki karşılıklarını kullanmamız gerekmekte.

email:this.emailCtrl

<input type="text" placeholder="email" class="form-control" formControlName="email">

bu haliyle uygulamamıza tarayıcıda bakacak olursak, bazı hatalardan dolayı register formunun düzgün bir şekilde gösterilmediğini görmemiz gerek.

Eğer uygulamanızı benim gibi, Angular CLI ile oluşturmadıysanız, Angular Reactive Form Modülünü, root modüle  import etmeyi unutmayın.  imports: [BrowserModule,ReactiveFormsModule, HttpModule ],

aldığımız hatanın sebebini tahmin etmişsinizdir, zaten tarayıcı konsoluna baktığınızda bu hata açıkca belirtilmekte.

ERROR Error: Cannot find control with name: ‘password2’

Login componentimiz de sorun yok çünkü o component password2 ve name isimli controllere ihtiyaç duymamaktaç Html tarafında *ngIf ile koşul koymuştuk hatırlarsanız. Ama register componentimiz bu iki eksta controle de ihtiyaç duymakta. Html tarafında bunları tanımlasakta, Component tarafında tanımlamadık,  çünkü bu iki control şartlı olarak tanımlanacak.

Şimdi componentimize geri dönelim ve bu iki şartlı controlü tanımlayalım.  Bu değişiklikle birlikte, componentimizin yeni hali

src/app/auth-form/auth-form.component.ts

import {Component, Input, OnInit} from '@angular/core';
import {FormBuilder, FormControl, FormGroup} from "@angular/forms";

@Component({
  selector: 'app-auth-form',
  templateUrl: './auth-form.component.html',
  styleUrls: ['./auth-form.component.css']
})
export class AuthFormComponent implements OnInit {

  @Input('formType') formType :String

  formTitle = 'Giris Yapin'
  buttonText='Giris'
  isLogin=true

  emailCtrl = new FormControl('')
  passwordCtrl = new FormControl('')

  /** Kosullu olarka olusturulacaklar*/
  nameCtrl:FormControl
  passwordCtrl2:FormControl

  authForm : FormGroup

  constructor(private fb:FormBuilder) {
    this.authForm = fb.group({
      email:this.emailCtrl,
      password:this.passwordCtrl
    })
  }

  ngOnInit() {
    if(this.formType =='Register'){
      this.buttonText = 'Kayit';
      this.formTitle = 'Kayit Ol';
      this.isLogin = false;

      /** Register oldugu icin isim ve sifre 2 yi de olustur*/
      this.passwordCtrl2 = new FormControl('')
      this.nameCtrl = new FormControl('')
      /** Gruba ekle*/
      this.authForm.addControl("password2",this.passwordCtrl2)
      this.authForm.addControl("name",this.nameCtrl)
    }
  }

  private handleForm(){
    console.log(this.authForm.value)
  }

}

ngOnInit içinde, componentimizin Login mi yoksa register mı olduğunu anladığımız noktada eğer “Register” ise, name ve password2 controllerimizide oluşturup, from grubumuza eklemiş olduk. Artık tarayıcıda baktığımızda iki formumuzunda doğru olarak gösterildiğini görebiliriz. Şimdi handleForm metodumuzu aşağıdaki gibi güncelleyip formumuzu test edelim.

src/app/auth-form/auth-form.component.ts

  private handleForm(){
    let form = this.authForm.value;
    
    if(this.isLogin){
      console.log("Giris Formu : ", form)
    }else{
      console.log("Kayit Formu : ", form)
    }
  
  }

tarayıcımızda form alanlarını doldurup, giriş veya kayıt butonlarina basıp konsola bakalım;

Formumuz ilk ihtiyaçlarını böylece karşılamış olduk, sırada ikinci ihtiyacımız olan, “Validations / Doğrulama” kısmı gelmekte.

Angular Form Validations in Code Driven  Forms / Form doğrulama işlemlerimiz.

Form doğrulama işlemlerimiz Code Driven yapıda gayet kolay, Angular form modülü ile gelen dahili doğrulama araçlarını yada kendi hazırladığımız doğrulama yardımcılarını kolayca kullanabilmekteyiz. İlk önce her form işleminde lazım olan ve angular ile gelen dahili yardımcıları kullanalım. Bunun için form controlleri oluşturduğumuz anda, ilgili doğrulamayıda istediğimiz belirtmemiz yeterli.

İlgili form controllerimizi aşağıdaki gibi güncellememiz yeterli

//Ortak controller
emailCtrl = new FormControl('' , Validators.required)
passwordCtrl = new FormControl('', [Validators.required, Validators.minLength(6)])
//Register e özel Controller
 this.passwordCtrl2 = new FormControl('',[Validators.required, Validators.minLength(6)])
 this.nameCtrl = new FormControl('', Validators.required)

FormControl sınıfından bir örnek oluşturuken, parametre olarak “default değer den sonra” ki bizim örneğimizde “” empty string , ikinci parametre olarak istediğimiz doğrulama yardımcısını eklememiz yeterli.  new FormControl('' , Validators.required) eğer birden fazla doğrulamamız varsa, ikinci parametreyi bir dizi (array) olarak vermemiz gerekmekte. new FormControl('',[Validators.required, Validators.minLength(6)])

Biz örneğimizde, bütün form controllerinin zorunlu alan olduğunu (required) ve şifre alanlarının ayriyeten en az 6 karakter uzunluğunda(minLength) olması gerektiğini belirtmiş olduk. Bir control e dilediğiniz sayıda doğrulama uygulayabilirsiniz. Dahili doğrulama yardımcılarına bu adresten  bakabilirsiniz.

Dahili doğrulamaların dışında, kendi ihtiyaçlarımıza özel “kendi doğrulama yardımcılarımızı / Custom Validations” nasıl yazacağımıza bakacağız ama öncesinde, bir kaç eksiğimizi daha giderelim. İlk olarak eğer form controllerimizden her hangi biri doğrulamayı geçemiyorsa, formumuzun gönderilemiyor olması lazım. Sonrasında da kullanıcıya neyin eksik yada yanlış olduğunu göstermemiz gerekmekte.

Bu işlem tahmin ettiğimizden daha kolay çünkü hem formumuzun tamamına hem de her control e tek tek ulaşma imkanımız var. İlk olarak eğer form da herhangi bir eksiklik varsa, formu gönderilebilir halinden çıkaralım. Bunun için, formu gönderdiğimiz nokta olan, button a bir küçük ekleme yapmamız yeterli olacaktır.

Butonumuzu tıklanamaz hale getirmek için , “disabled” özelliğini kullanabiliriz.

<button [disabled]="!authForm.valid" class="btn btn-sm btn-success">{{buttonText}}</button>

authForm bir formGroup örneği olduğu için, authForm.valid gibi bir çok kontrolü hazır olarak sunmakta, bunlardan bazıları ;


.dirty // kullanıcı her hangi bir değer girene kadar “false” değeri döndürecek.
.valid // doğrulama testimizi geçiyorsa “true” aksi takdirde “false”
.errors //doğrulama ile ilgili bütün hataların tutulduğu nesne
.pristine // isim.dirty kontrolunun tersi
.touched // kullanıcın bir değişiklik yapıp yapmadığını değil, elemente hiç focus olup olmadığını takip eden değer
.status // VALID veya INVALID
.valueChanges // Observable nesnesi, input daki her değişiklikle aktif olan ve her bir değişikliği takip edebileceğimiz event/olay
.hasError(“required”) // parametre olarak geçtiğimiz doğrulama için bir hata var mı yok mu kontrol edebileceğimiz method.

yukarıdaki liste hem form grubumuz için hemde tek tek her control için kullanılabilmekte. Bu da çok ciddi bir esneklik demek. Biz giriş / kayıt butonuna , eğer form invalid/ geçersiz ise butonu disabled moduna sokacak küçük bir ekleme yaptık ve formumuz artık geçersiz olduğunda gönderilemeyecek. Şimdi sıra hata mesajlarını göstermeye geldi. Bunun için bir kaç farklı yöntem olsada biz en çok kullanılan, “her bir control için ayrı mesaj” yaklaşımı kullanalım.

Angular,  form control kullanarak eklediğimiz her input için, “eğer bir hata varsa yada her hangi bir değişiklik yapıldıysa” ilgili control e html tarafında bir css sınıfı ekleyecek . Bu sınıflardan bizim kullanacaklarımız;

State Class if true Class if false
The control has been visited. ng-touched ng-untouched
The control’s value has changed. ng-dirty ng-pristine
The control’s value is valid. ng-valid ng-invalid

Bu sınıfları kullanma nedenimiz, kullanıcıya daha fazla bilgi verebilmek, bu sınıflara göre küçük bir parça css ekleyerek formumuzu daha anlaşılır bir hale getirebilirz. Biraz css ekleyerek devam edelim,

src/app/auth-form/auth-form.component.css

input.ng-invalid {
  border: 3px red solid;
}

Tarayıcıda şuanki haliyle formumuz;

Kayit butonun disabled olduğu resimden belli olmuyor olabilir ama şuan tıklanamaz durumda ve , geçerli değer taşımayan controller kırmızı bir “border” a sahip. Kullanıcımız için, bir şeylerin yolunda olmadığını anlaşılır durumda olsada, tam olarak neyin eksik yada yanlış olduğu tam açık değil. Şimdi hata mesajı ekleyerek devam edelim. Ben uzatmamak için sadece email alanı için bu eklemeye yapacağım diğer alanlar içinde kullanım aynı.

Form içinde uygun gördüğümüz bir yere (muhtemelen ilgili control ün öncesi yada sonrasında ) aşağıdaki gibi bir kontrol eklememiz yeterli.

src/app/auth-form/auth-form.component.html

  <div *ngIf="!authForm.valid" class="alert alert-warning sm">
        <div *ngIf="authForm.get('password').hasError('required')">Sifre alani zorunludur</div>
        <div *ngIf="authForm.get('password').hasError('minlength')">Sifreniz en az 6 karakter olmak zorunda</div>
  </div>

form grubmuzun geçerli durumda değilse   <div *ngIf="!authForm.valid" class="alert alert-warning sm"> , hataları bul ve göster demiş olduk. Hatalarımızı bulmanın bir den fazla yolu olsada, muhtemeln en kolayı , ilgili control ün .hasError() metodunu çağırmak. Bunun için,  *ngIf="authForm.get('password').hasError('required')" kontrolünü yaptık. FormGrubumuza “password isimli control ü ve , bir hatası olup olmadığını bana bildir” demiş olduk. “required” parametresi ise , bakmak istediğimiz hata türünü belirtmiş oldu.

Custom Validations / Kendi doğrulama yardımcımız oluşturmak.

Kendi özel ihtiyaçlarımız için doğrulama oluşturmak adına ihtiyacımız olan sadece bir function tanımlayıp bu function dan “null / eğer hata yoksa” veya ” errorName:true/ eğer hata varsa” şeklinde bir değer döndürmek. Böylece ilgili controlün .hasError() metodu ya bir “null / hata yok” değeri yada “hata ismi : tru” değeri döndürmiş olacak.

Bu fonksiyon bir form control nesenini parametre değeri olarak alacak. Biz email için böyle bir özel kontrol oluşturalım. Componentimizde, aşağıdaki gibi bir metod tanımlayarak bu işlemi gerçekleştirebiliriz.

src/app/auth-form/auth-form.component.ts

// email control e dogrulama metodumuzu ata
emailCtrl = new FormControl('' , [Validators.required,AuthFormComponent.isEmailValid])

//dogrulama metodumuz
static isEmailValid(control: FormControl){
    // deger gecerli bir email mi?
    const email= control.value;

    return email.indexOf('@') > 0 ? null : { invalidEmail: `gecersiz email!` };
  }

html içinde , hatamızı göstermek için

src/app/auth-form/auth-form.component.html

   <div *ngIf="!authForm.valid" class="alert alert-danger sm">
        <div *ngIf="authForm.get('email').hasError('required')">Email Alani zorunludur!</div>
        <div *ngIf="authForm.get('email').hasError('invalidEmail')">Email Gecersiz!!!</div>
   </div>

Formumuza tarayıcıda tekrar bakacak olursak ;

 

 

Son olarak,  model-driven yaklaşımı ile geliştirdiğimiz formlarda, değişikliklerin dinlenmesi / takip edilmesi konusu bakalım.

Observable valueChanges   – Observable alt yapısı ile değişiklik takibi

Formumuzdaki değişiklikleri takip için iki alternatifimiz var, birincisi formun tamamını dinlemek , hangi control de olduğu önemli olmadan tüm değişikliklere abone olmak.

this.authForm.valueChanges
      .subscribe(formdakiDegisiklik =>{
        console.log("Formda Degisiklik oldu  : ", formdakiDegisiklik)
      })

İkinci seçenek ise, her hangi bir Control ü tek başına dinlemek. Örneğin , yukarıdaki formumuzda, name alanındaki her bir değişikliği dinlemek ve buna göre bazı işlemler yapmak için,  Control sınıfı ile oluşturduğumuz her bir control için kullanılabilir olan “valueChanges” observable ı dinleyebiliriz.

  this.nameCtrl.valueChanges.subscribe((yeniDeger) => {
        if (yeniDeger && yeniDeger.indexOf('@') >= 0) {
          console.log('@ işaretini isim alani içinde kullanamazsınız');
        }
      });

nameCtrl.valueChanges bize bir Observable nesnesi döndürdüğü için isim alanında yapılacak her bir değişikliği, bu stream / akıma subscribe/abone olarak dinleyip gerekli işlemleri yapabilmekteyiz.

Bu yazimizda Angular için Code Driven yapısına genel olarak bakmaya çalıştık. Bir sonraki yazıda diğer alternatifimiz olan Template Driven form a bakarak devam edelim inş.

Kolay Gele.

 

 

 

 

6 thoughts on “Angular ile(2 & 4) form kullanımı ve form doğrulama işlemleri( validations ) – Code Driven/Reactive Forms

  1. Merhaba
    Gerçekten öğretici ve oldukça iyi bir çalışma yapmışsınız. Elinize sağlık. Videoları tamamlamanızı sabırsızlıkla bekliyorum. Youtube da koyarsanız yada indirme imkanı verirseniz ofline olarak faydalanma imkanı tanımış olursunuz ki çok sevinirim.

  2. Hüseyin Hocam Merhaba,
    Ben ng new proje-adi komutuyle proje oluşturduğumda app.module.ts içine
    import { HttpModule } from “@angular/http”; gibi istediğim modülleri default olarak nasıl getirttirebilirim ?

Leave a Reply

Your email address will not be published. Required fields are marked *