اعتبارسنجی FormBuilder و ngModel - بخش ۴-۲

23 شهریور 1399
angular2main-validation

در فصل گذشته به چگونگی ساخت یک فرم در انگولار ۲ اشاره کردیم اما این مبحث ناتمام مانده‌ است زیرا هنوز به FormBuilderها  و Validationها نپرداختیم. سخن کوتاه می‌کنیم و ادامه ی مبحث ایجاد فرم‌ها در انگولار ۲ را در پیش می‌گیریم. توجه داشته باشید که مطالب و مباحث مربوط به فرم‌ها کاملا پیوسته هستند و حتما در ابتدا بخش ۴-۱ را مطالعه بفرمایید.

استفاده از FormBuilder

جهت استفاده از FormBuilder یک آرگومان به سازنده کلاس کامپوننت تزریق می‌کنیم.

یک سوال: تزریق یا inject به چه معنی‌ست؟
پاسخ: در سطوح بالاتر، تزریق وابستگی Dependency Injection به معنای راهی برای اطلاع به انگولار جهت معرفی ملزومات توابع برای یک کامپوننت است.

بنابراین داخل کلاس کامپوننت کدهای زیر را اضافه می‌کنیم:

export class AppComponent {
  myForm: FormGroup;
  
  constructor(fb: FormBuilder){
    this.myForm = fb.group({
      'sku': ['ABC123']
    })
  }
  
  onSubmit(form: any): void{
    console.log('کد محصول ثبت شده برابر است با:', form);
  }
}

حین تزریق یک نمونه از FormBuilder ساخته خواهد شد که آن را به متغییر fb انتساب کرده‌ایم. اینجا دو تابع اصلی وجود دارند که در FormBuilder استفاده می‌شوند:

  • control: یک FormControl جدید می‌سازد
  • group: یک FormGroup جدید می‌سازد

نکته قابل توجه این است که ما یک نمونه متغییر به نام myForm در این کلاس ایجاد کردیم. درواقع myForm از نوع یک FormGroup‌ است و ما یک FormGroup را ایجاد کرده و توسط ()fb.group آنرا فراخوانی کردیم. group. یک شیء به همراه کلید و مقدارش را در اختیار ما قرار می‌دهد که یک FormControl‌ مشخصی را در این گروه دنبال می‌کند.

در این مثال یک کنترل به نام sku که دارای مقدار ["ABC123"] است، ایجاد کرده‌ایم. این خط مشخص می‌کند که مقدار پیشفرض این کنترل برابر ABC123 است.

هم اکنون یک myForm داریم که می‌خواهیم از آن در View استفاه کنیم (یعنی باید این myForm را به المان‌های خروجی خود در قالب بایند کنیم)

استفاده از myForm در View قالب

هم اکنون باید تگ <form> را جهت استفاده از myForm در قالب خود تغییر دهیم. اگر به یاد داشته باشید در آخر مباحث بخش ۴-۱ اشاره کردیم که ngForm هنگامیکه از FormsModule استفاده می‌کنیم، به صورت خودکار به تمام فرم‌ها اضافه می‌شود. همچنین ngForm فرم FormGroup خود را ایجاد می‌کند. بسیار خب! در این مثال نمی‌خواهیم از یک FormGroup خارجی استفاده کنیم. بلکه قصد داریم از نمونه‌ی متغییر myForm که آن را ایجاد کردیم برای ساخت یک فرم بهره‌ ببریم. انگولار ۲ دستورهای دیگری را برای زمانیکه یک FormGroup خارجی را می‌خواهیم مورد استفاده قرار دهیم در اختیار ما گذاشته است. نام این دستور formGroup است که به صورت زیر مورد استفاده قرار می‌گیرد:

<form [formGroup] = "myForm">

در واقع به انگولار ۲ اطلاع دادیم که می‌خواهیم از یک myForm به عنوان FormGroup استفاده کنیم. همچنین نیاز به تغییر onSubmit ضروری است جهت استفاده از myForm به جای f ضروری است. زیرا myForm ما با تنظیمات دلخواه خودمان ایجاد شده است.

همچنین به عنوان آخرین نکته جهت کار کردن نرم افزار، باید FormControl خودمان را به تگ input بایند (متصل) کنیم. به یاد داشته باشید که ngControl یک شیء جدید از FormControl ایجاد می‌کند و آن را به FormGroup والد خود متصل می‌کند. اما در این مثال از FormBuilder برای ساختن FormControlهای خود بهره‌ می‌بریم.

هنگامیکه می‌خواهیم از یک FormControl خارجی در کدهای خود استفاده کنیم تگ input را به صورت زیر تغییر می‌دهیم:

<div class="form-group">
    <label for="skuInput" class="col-sm-2 control-label">کد محصول</label>
    <div class="col-sm-10">
      <input type="text"
             class="form-control"
             id="skuInput"
             [formControl] = "myForm.controls['sku']"
             placeholder="کد محصول را وارد کنید..." >
    </div>
 </div>

و در نهایت کدهای HTML و DOM‌ ما در فایل template باید به صورت زیر باشد:

<div class="row">
  <div class="col-md-8 container-center">
    <div class="box box-info">
      <div class="box-header with-border">
        <h3 class="box-title">ثبت کد محصول</h3>
      </div>
      <div class="box-body">
        <form [formGroup]="myForm" (ngSubmit)="onSubmit(myForm.value)" class="form-horizontal">
          <div class="form-group">
            <label for="skuInput" class="col-sm-2 control-label">کد محصول</label>
            <div class="col-sm-10">
              <input type="text"
                     class="form-control"
                     id="skuInput"
                     [formControl] = "myForm.controls['sku']"
                     placeholder="کد محصول را وارد کنید..." >
            </div>
          </div>
          <div class="box-footer">
            <button type="submit" class="btn btn-info pull-left">ذخیره</button>
          </div>
        </form>
      </div>
    </div>
  </div>

نکته: همیشه به یاد داشته باشید :

  • برای ساخت یک FormGroup و FormControl ضمنی (implicitly) جدید از ngForm و ngModel‌ استفاده می‌شود.
  • برای بایند کردن اطلاعات به یک FormGroup و FormControl آماده از formGroup و formControl استفاده می‌شود.

اضافه کردن اعتبارسنجی (Validation)

توجه دارید که کاربران یک وب سایت همواره به صورت منظم و دقیق فرم‌ها را پر نمی‌کنند. گاهی فراموش می‌کنند و گاهی می‌خواهند فرآیند را به سرعت طی کرده و روی دکمه‌ی ذخیره یا ثبت اطلاعات کلیک کنند. حال برای جلوگیری از این اتفاق باید اعتبارسنجی هایی روی فرم‌ها اعمال شود تا کاربر متناسب با پیام دریافتی بتواند اطلاعات را تکمیل کند. به همین منظور از validatorها استفاده خواهیم کرد.

اعتبارسنجی در انگولار ۲ توسط ماژول Validators فعال می‌شود که ساده‌ترین نوع اعتبارسنجی برابر Validators.required است که به کاربر می‌گوید پر کردن این فیلد الزامی‌ست. برای استفاده از اعتبارسنجی همواره باید دو موضوع را مد نظر داشته باشید:

  1. انتساب یک اعتبارسنجی به شیء FormControl
  2. چک کردن وضعیت اعتبارسنجی در View و اعمال اکشن برای آن

برای انتساب یک اعتبارسنج به یک شیء FormControl به عنوان دومین آرگومان آن را به سازنده‌ی پیشفرض کلاس FormControl ارسال می‌کنیم:

let control = new FormControl('sku', Validators.required);

در مثال قبلی به دلیل استفاده از FormBuilderها ویرایش به صورت زیر انجام می‌پذیرد:

constructor(fb: FormBuilder){
    this.myForm = fb.group({
      'sku': ['', Validators.required]
    });
    this.sku = this.myForm.controls['sku'];
  }

حال باید اعتبارسنجی را در view و قالب نرم‌افزار خود انجام دهید. منعطف‌ترین راه اضافه کردن یک نمونه متغییر در کلاس تعریف شده کامپوننت شماست.  در اینجا برای sku تغییرات را ارائه خواهیم داد:

import { Component } from '@angular/core';
import {FormGroup, FormBuilder, Validators, AbstractControl} from "@angular/forms";

@Component({
  selector: 'demo-form-sku',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  myForm: FormGroup;
  sku: AbstractControl;

  constructor(fb: FormBuilder){
    this.myForm = fb.group({
      'sku': ['', Validators.required]
    });
  }

  onSubmit(form: any): void{
    console.log('کد محصول ثبت شده برابر است با:', form);
  }
}

به نکات زیر توجه کنید:

  • sku: AbstractControl در ابتدای کلاس تعریف شد
  • this.sku پس از ساخت myForm توسط FormBuilder انتساب داده شد

این موضوع بسیار ارزشمند است زیرا هرجا درون View خود می‌توانیم به sku رفرنس بدهیم. حال با اعتبارسنجی sku شروع می‌کنیم.

پیام‌های اعتبارسنجی فرم

در این بخش قصد داریم اعتبارسنجی یک فیلد را مورد بررسی قرار داده و در صورت وجود هرگونه خطا پیام مشخصی ارائه شود. بنابراین مجموعه‌ی کد زیر را به دستورات خود در HTML اضافه می‌کنیم:

<div *ngif="!sku.valid" class="alert-danger">کد محصول وارد شده نامتعبر است</div>

توجه داشته باشید که myForm یک FormGroup است و یک FormGroup مورد تایید است اگر و فقط اگر تمام فرزندان FormControls آن مورد تایید باشد.

پیام‌های اعتبارسنجی فیلد‌ها

همچنین می‌توانید اعتبارسنجی را برای یک فیلد مشخص انجام دهید درصورتیکه FormControl آن فیلد معتبر نباشد:

<div *ngIf="!sku.valid" class="alert-danger">کد محصول وارد شده نامتعبر است</div>
<div *ngIf="sku.hasError('required')" class="alert-danger">وارد کردن کد محصول ضروری است</div>

اعتبارسنجی برای تغییر رنگ فیلدها

برای تغییر رنگ فیلدهایی که اعتبارسنجی آنها با مشکل مواجه شده است می‌توانید از کد زیر استفاده کنید. البته به دلیل استفاده از فریم ورک بوت‌استراپ برای تغییر رنگ فیلدها از کلاس has-error بهره‌ می‌بریم.

<div class="form-group  field" [class.error]="!sku.valid && sku.touched">
            <label for="skuInput" class="col-sm-2 control-label">کد محصول</label>
            <div class="col-sm-10">
              <input type="text"
                     class="form-control"
                     id="skuInput"
                     [formControl] = "myForm.controls['sku']"
                     placeholder="کد محصول را وارد کنید..." >
            </div>

همانطور که ملاحظه می‌کنید علاوه بر sku.valid! از sku.touched استفاده کرده‌ایم تا تنها و تنها اگر اعتبارسنجی به همراه تلاش برای تغییر وجود داشت فیلد موردنظر قرمز شود.

اعتبارسنجی‌های دلخواه

در برخی مواقع نیاز داریم تا اعتبارسنجی های دلخواه خود را روی هر فیلد اعمال کنیم.برای اینکار یک تابع دلخواه تعریف می‌کنید و اعتبارسنجی خود را درون آن تابع قرار می‌دهید:

function skuValidator(control: FormControl): { [s: string]: boolean } {
 if (!control.value.match(/^123/)) {
 return {invalidSku: true};
 }
}

سپس کد موجود در constructor کامپوننت را به صورت زیر تغییر می‌دهیم:

constructor(fb: FormBuilder) {
 this.myForm = fb.group({
 'sku': ['', Validators.compose([
 Validators.required, skuValidator])]
});

و در نهایت برای قالب HTML کدهای زیر را اعمال کرده و صفحه را مجددا بارگذاری می‌کنیم:

<div *ngIf="sku.hasError('invalidSku')" class="alert-danger">کد محصول باید با مقدار <span>123</span> شروع شود.</div>

ngModel

ngModel‌ یک دستورالعمل خاص است که از آن برای بایند کردن یک مدل به یک فرم استفاده می‌کنند. در واقع جهت متغییر کردن مقدار ورودی یک فرم از ngModel‌ استفاده می‌شود تا متناسب با آنچه کاربر تایپ می‌کند تغییرات و یا اعتبارسنجی‌ها شروع به پردازش کنند. بنابراین کد مثال قبل را جهت استفاده از ngModel به صورت زیر تغییر می‌دهیم:

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

@Component({
  selector: 'demo-form-sku',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  myForm: FormGroup;
  sku: string;

  constructor(fb: FormBuilder){
    this.myForm = fb.group({
      'sku': ['', Validators.required]
    });
  }

  onSubmit(value: string): void{
    console.log('کد محصول ثبت شده برابر است با:', value);
  }

}

حال به تگ input قالب HTML متغییر ngModel را مشخص می‌کنیم:

<!-- Input addon -->
<div class="row">
  <div class="col-md-8 container-center">
    <div class="box box-info">
      <div class="box-header with-border">
        <h3 class="box-title">ثبت کد محصول</h3>
      </div>
      <div class="box-body">
        <div class="info-box">کد محصول وارد شده برابر است با: {{ sku }}</div>
        <form [formGroup]="myForm" (ngSubmit)="onSubmit(myForm.value)" class="form-horizontal">
          <div class="form-group  field" [class.error]="!sku.valid && sku.touched">
            <label for="skuInput" class="col-sm-2 control-label">کد محصول</label>
            <div class="col-sm-10">
              <input type="text"
                     class="form-control"
                     id="skuInput"
                     [formControl] = "myForm.get('sku')"
                     [(ngModel)]="sku"
                     placeholder="کد محصول را وارد کنید..." >
            </div>
          </div>
          <div *ngIf="!sku.valid" class="alert-danger">کد محصول وارد شده نامتعبر است</div>
          <div *ngIf="sku.hasError('required')" class="alert-danger">وارد کردن کد محصول ضروری است</div>
          <div class="box-footer">
            <button type="submit" class="btn btn-info pull-left">ذخیره</button>
          </div>
        </form>
      </div>
    </div>
  </div>
</div>
<!-- /.box -->

در این بخش آموزش کامل و جامع کار با FormBuilderها، Validationها و ngModel را یاد گرفتید. حال با دانش برنامه‌نویسی خود می‌توانید به تولید فرم‌های مختلف با استفاده از انگولار ۲ بپردازید. در جلسه آینده مباحث مربوط به تقاضاهای HTTP، استفاده از Apiها را می‌آموزید.

برای افزایش تمرکز کاربران عزیز و جلوگیری از طولانی شدن مطالب، هر بخش را به قسمت‌های کوچکتری تبدیل کرده‌ایم. در لیست زیر تمام بخش‌ها و زیربخش‌های آموزشی مجموعه‌ی انگولار ۲ در اختیار شما قرار گرفته است.

توجه: دوستان عزیز آموزش ویدیویی انگولار ۵ از مقدماتی تا پیشرفته به زبان فارسی را می‌توانید با کلیک روی اینجا یاد بگیرید. (این دوره در حال برگزاری است)

آموزش حرفه ای انگولار ۵ به زبان فارسی


فصل ۱

فصل ۲

فصل ۳

فصل ۴

فصل ۵

فصل ۶

نویسنده شوید
دیدگاه‌های شما (1 دیدگاه)

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

زیور
21 فروردین 1397
با سلام من وقتی کد شمارو وارد میکنم error contextمیده برای المنتinput typeممکنه راهنمایی کنید

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.