آشنایی با فرم‌ها (NgForm و NgModel) - بخش ۴-۱

02 اسفند 1395
angular2main-forms-ngform1

اینک وارد بحث جدیدی از سری دوره‌های آموزش فارسی انگولار ۲ می‌شویم. از عنوان این فصل مشخص است که با چه مقوله‌ی مهمی برخورد کردیم. کاملا درست فکر می‌کنید! فرم‌ها به عنوان مهم‌ترین و پیچیده‌ترین بخش‌های هر وب‌سایت و یا نرم‌افزار تحت وب را تشکیل می‌دهند. اهمیت این فرم‌ها زمانی مشخص می‌شود که بخواهید اطلاعاتی را از طریق یک دکمه و Event به مکان دیگری (که می‌تواند دیتابیس و یا هر چیز دیگه‌ای باشد) انتقال دهید. در ابتدا شاید به این فکر کنید که فرم‌ها را می‌توان با یک تگ input ساخت و به راحتی از کاربر تقاضا کرد که اطلاعات خود را وارد باکس موردنظر کند. اما آیا واقعا کار به همین سادگی است؟ مسلما جواب منفی است. برای روشن تر شدن این موضوع چند چالش عمده فرم‌ها را ارائه خواهیم داد:

  • ورودی‌های (inputs) فرم‌ها به منظور تصحیح کننده‌ی اطلاعات در سمت سرور و سمت کاربر هستند
  • تغییرات اطلاعات درون هر باکس فرم باید سریعا به سرور گزارش داده شود
  • همواره باید اعتبارسنجی روی هر فیلد صورت بگیرد تا راه گریزی برای کاربران وجود نداشته باشد
  • یک رابط کاربری (UI) مناسب مورد نیاز است تا تغییرات و خطاها را به کاربر گزارش دهد
  • فیلدهای وابسته منطق پیچیده‌تری دارند
  • همواره باید فرم‌ها را بدون وابستگی به سلکتورهای DOM تست کرد

حال انگولار ۲ به عنوان یک راهنمای بلامنازع به شما کمک می‌کند تا این مسائل و چالش‌ها را برطرف کنید.

  • FormControl‌ها اطلاعات ورودی هر فرم را کپسوله کرده و شیءهایی را برای تجزیه و تحلیل در اختیار ما قرار می‌دهند
  • Validatorها توانایی ارزشیابی و اعتبارسنجی هر فیلد را برای ما به ارمغان می‌اورند
  • Observerها به عنوان ناظر فرم‌ها را بررسی کرده و منتظر تغییر کوچک و در نهایت دریافت پاسخ از سرور هستند

حال در ادامه‌ی توضیحات این بخش به صورت مرحله به مرحله نحوه ساخت یک فرم را آموزش می‌دهیم. مثالها از ساده‌ترین سطح ممکن شروع و به پیچیده‌‍ترین حالت ختم می‌شوند.

FormControlها و FormGroupها

دو شیء اساسی و بنیادی در فرم‌های انگولار ۲ FormControl و FormGroup هستند.

FormControl

یک FormControl برای نمایش یک فیلد ورودی بکار گرفته می‌شود که کوچکترین عضو یک فرم انگولار بحساب می‌آید. به بیان دیگر FormControlها به عنوان یک فیلد ورودی با تگ input در فرم‌های انگولار شناخته شده که کوچکترین المان یک فرم محسوب می‌شود. FormControl‌ها مقادیر فیلدها را کپسوله می‌کنند و شرایط مختلف آنها اعم از اعتبارسنجی، تغییر متن یا خطا را مورد ارزیابی قرار می‌دهند. برای نمونه در مثال زیر نحوه استفاده از FormControlها را مورد بررسی قرار می‌دهیم:

// ساخت یک فرم کنترلر جدید به همراه مقدار nate
let nameControl = new FormControl("Nate");

let name = nameControl.value; // -> Nate

// هم اکنون می‌توان برای این مقدار مشخص دستورهای ارزیابی اعتبار سنجی و خطا را مورد بررسی قرار داد
nameControl.errors // -> StringMap<string, any> of errors
nameControl.dirty // -> false
nameControl.valid // -> true
// etc.

همانگونه که در مثال فوق ملاحظه کردید ابتدا یک فیلد ورودی به نام nameControl تعریف کرده و مقدار پیش‌فرض آن را nate قرار دادیم. حال برای دسترسی به این مقدار از دستور nameControl.value  استفاده خواهیم کرد. علاوه بر متد value سایر متدها مانند errors, dirty و valid وجود دارند که به شرح زیر عمل می‌کنند:

  • nameControl.errors -> مجموعه‌های خطاهای ناشی از Validation فرم‌ها را به صورت رشته باز می‌گرداند. در صورتیکه خطایی وجود نداشته باشد مقدار null همواره return‌ خواهد شد.
  • nameControl.dirty -> یک فیلد کنترل هنگامیکه تغییر کند با حالت dirty شناخته می‌شود.
  • nameControl.valid -> هنگامیکه یک فرم valid باشد استفاده می‌شود

تمام ویژگی‌های فوق زمانی که درست یا غلط باشند مقادیر True و False را باز می‌گردانند.

همانند سایر مباحث، در انگولار ۲ یک کلاس تحت عنوان FormControl داریم که به DOM به همراه یک صفت formControl متصل می‌شود. در مثال زیر نحوه استفاده کردن از این فرم کنترلر را در کد HTML یا DOM مورد بررسی قرار می‌دهیم:

<input type="text" [formControl]="name" />

این خط یک شیء FormControl جدید درون فرم ما ایجاد کرد. در ادامه به نحوه کارکرد آن اشاره خواهیم کرد.

FormGroup

بسیاری از فرم‌ها، بیش از یک فیلد دارند. بنابراین ما به تعداد بیشتری FormControls نیاز داریم و اگر بخواهیم اعتبارسنجی فرم خود را بررسی کنیم، باید آرایه‌ای از FormControlها را ایجاد کرده و هر یک را ارزیابی کنیم. این کار بسیار زمان بر و از نظر مهندسی طراحی نرم‌افزار اشتباه می‌باشد لذا برای حل این مسئله از FormGroupها استفاده می‌شود که در واقع مجموعه‌ای از FormControlها را در بر می‌گیرند.

یک نمونه جهت ایجاد FormGroupها:

let personInfo = new FormGroup({
    firstName: new FormControl("Nate"),
    lastName: new FormControl("Murray"),
    zip: new FormControl("90210")
})

بنابراین می‌توانیم status یا value را برای personInfo بررسی کنیم:

personInfo.value; // -> {
//    firstName: "Nate",
//    lastName: "Murray",
//    zip: "90210"
// }

personInfo.errors // -> StringMap<string, any> of errors
personInfo.dirty // -> false
personInfo.valid // -> true

// etc.

اولین فرم ما

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

تصویر زیر نمایانگر فرمی است که مدنظر ما می‌باشد:

ساخت فرم در انگولار ۲

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

فرم ما بسیار ساده است: یک ورودی برای sku‌ به همراه یک برچسب و یک دکمه‌ی ‌«ذخیره» برای ثبت اطلاعات در اختیار داریم. اجازه بدهید این فرم را تحت عنوان یک کامپوننت ایجاد کنیم. اگر به یاد داشته باشید، برای تعریف یک کامپوننت به ۳ قسمت نیاز داریم:

  • تنظیمات مفسر @Component()
  • ساخت قالب
  • ایجاد توابع دلخواه درون کلاس کامپوننت

شروع می‌کنیم:

بارگذاری FormsModule

برای ایجاد کردن یک فرم جدید در انگولار ۲ باید مطمئن شویم که کتابخانه‌‌های موردنظر فرم‌ها درون NgModule فراخوانی یا Import شده باشند. همواره دو راه برای استفاده از فرم‌ها در انگولار ۲ وجود دارد که هر دو روش را به دقت بررسی خواهیم کرد. روش اول استفاده از FormsModule ها و روش دوم استفاده از ReactiveFormsModule می‌باشد. برای اینکه هر دو روش را توضیح دهیم، هر دو ماژول را در NgModule فراخوانی می‌کنیم. بنابراین فایل app.ts را به صورت زیر ویرایش می کنیم:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';

import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent,
  ],
  imports: [
    BrowserModule,
    FormsModule,
    ReactiveFormsModule,
    HttpModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

اضافه کردن این خطوط به کد برنامه تضمینی است جهت استفاده از دستورهای فرم‌ها داخل view‌ نرم افزار شما. در واقع FormsModule‌، مجموعه‌ای از دستورهای موردنیاز برای طراحی قالب یک فرم (مثال: ngModel و NgForm) را در اختیار شما قرار می‌دهد. درحالیکه کتابخانه ReactiveFormsModule دستورهایی مشابه:‌ formControl و ngFormGroup‌ را در اختیار می‌گذارد.

فرم ساده کد محصول:‌ مفسر @Component

هم اکنون شروع به بازنویسی کامپوننت می‌کنیم:

import { Component } from '@angular/core';

@Component({
    selector: 'demo-form-sku',

در این بخش یک سلکتور (selector) به نام demo-form-sku‌ تعریف کردیم. اگر به یاد داشته باشید، سلکتورها به انگولار می‌گویند که چه المانی از این کامپوننت برای نمایش در خروجی قالب مورد استفاده قرار می‌گیرد. در واقع تگ موردنظر را جهت استفاده در کد HTML تعیین می‌کند:

<demo-form-sku></demo-form-sku>

فرم ساده کد محصول:‌ template یا قالب

حال برای کدنویسی قالب فرم موردنظر، فایل app.component.html را باز کرده و کدهای زیر را جایگزین می‌کنیم:

<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 #skuForm="ngForm" (ngSubmit) = "onSubmit(skuForm.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"
                     name="sku"
                     placeholder="کد محصول را وارد کنید..." ngModel>
            </div>
          </div>
          <div class="box-footer">
            <button type="submit" class="btn btn-info pull-left">ذخیره</button>
          </div>
        </form>
      </div>
    </div>
  </div>
</div>

شگفت‎‌زده شده‌اید؟ کاملا حق با شماست! یک سری دستورها را فقط کپی پیست کرده‌اید! اما نگران نباشید. در این بخش به صورت کامل توضیحات مربوط به مثال فوق را ارائه خواهیم داد.

form و NgForm

در ابتدای کار FormsModule را import کردیم تا بتوانیم از امکانات NgForm در view بهره‌مند باشیم. به یاد داشته باشید که هر گاه در انگولار ۲ از دستوری استفاده کردیم، در واقع آن را به تمام المان‌هایی که شامل آن سلکتور هستند اتصال داده‌ایم.

NgForm به صورت غیرآشکارا یک سری کلاس‌ها را به فرم ما اضافه می‌کند: یعنی اگر FormsModule را فراخوانی یا import کنیم، NgForm به صورت خودکار به تمام تگ‌های <form> اضافه خواهد شد. حال دو تابع بسیار مهم وجود دارد که NgForm در اختیار ما قرار می‌دهد:

  1. یک FormGroup به نام ngForm
  2. یک (ngSubmit) خروجی

همانگونه که ملاحظه می‌کنید هر دو تابع فوق درون تگ <form> ما قرار گرفته است:

<form #skuForm="ngForm" (ngSubmit) = "onSubmit(skuForm.value)" class="form-horizontal">

در واقع، در ابتدای کار عبارتی معادل skuForm = "ngForm# را ایجاد کردیم. سینتکس variableName=directive به ما اطلاع می‌دهد که یک متغییر محلی برای این ویو ساخته شد. در اینجا ما یک نام مستعار یا متغییر تحت عنوان skuForm# برای ngForm قرار داده ایم. حال این سوال پیش می‌آید که نوع شیء ngForm چیست؟ جواب سوال: نوع آن FormGroup است. بدین معنی که ما از skuForm به عنوان یک FormGroup در ویو خود استفاده کرده‌ایم.

در انتها اطلاعات را روی اکشن ngSubmit ارسال خواهیم کرد که با سینتکس زیر مشخص شده است:

(ngSubmit) = "onSubmit(skuForm.value)"
  • (ngSubmit) : از NgForm آمده است
  • onSubmit() : به عنوان یک تابع داخل کلاس کامپوننت تعریف شده و اجرا خواهد شد
  • skuForm.value : کلمه skuForm یک FormGroup است که در بالا تعریف کردیم و .value مقدار این FormGroup را باز می‌گرداند

در یک خط می‌توان تمام مراحل بالا را به زبان ساده‌تری بیان کرد:

هنگامیکه من فرم را ذخیره کردم تابع onSubmit در کامپوننت اجرا شده و مقادیر ورودی‌ها را به عنوان یک آرگومان ارسال خواهد شد.

input و NgModel

تگ input دارای یک سری ویژگی‌ها و صفات است که برای آشنایی با آنها باید HTML‌ و مباحث Classهای هر المان را آموزش دیده باشید. طبیعتا از توضیح آنها صرف نظر می‌کنیم و به NgModel می‌پردازیم:

دستور NgModel یک سلکتور (selector) از ngModel را مشخص می‌کند. بدین معنی‌ که می‌توان آن را با استفاده از صفت ngModel="whatever" به تگ input‌ متصل کرد. در این مثال، صفت ngModel بدون مقدار است. NgModel یک FormControl جدید را ایجاد کرده که به صورت خودکار به FormGroup والد خود اضافه می‌شود و سپس اطلاعات را به یک المان DOM بایند می‌کند. به بیان ساده‌تر، NgModel یک رابطه بین تگ input و FormControl توسط نام sku برقرار می‌کند.

بیشتر بخوانید: تفاوت بین NgModel‌ و ngModel : در حالت کلی هنگامیکه از کلمه‌ای با ساختار PascalCase استفاده کردیم (مانند NgModel) به یک کلاس مشخص اشاره می‌کنیم اما اگر از کلمه‌ای با ساختار CamelCase (مانند: ngModel) بهره‌بردیم، به یک سلکتور (selector) از دستورالعمل اشاره کرده‌ایم که تنها در قالب‌های HTML و DOM قابل استفاده هستند.

فرم ساده کد محصول:‌ تعریف کلاس کامپوننت

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

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

با مطالعه‌ی کد بالا متوجه خواهید شد که پیچیدگی خاصی وجود ندارد. تابع onSubmit یک آرگومان به نام form از نوع any دارد که به محض اجرای تابع به خروجی مرورگر و در کنسول آن نمایش داده خواهد شد.

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

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

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

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


فصل ۱

فصل ۲

فصل ۳

فصل ۴

فصل ۵

فصل ۶

نویسنده شوید

دیدگاه‌های شما (2 دیدگاه)

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

مجتبی
21 آبان 1396
شدلعمشق این چیه اون بالا مونده !

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

روکسو
22 آبان 1396
با سلام و احترام ویرایش شد.

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

روکسو
22 آبان 1396
با سلام و احترام ویرایش انجام شد.

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

میثم صحراگرد
12 تیر 1396
سلام ممنون مطلب خوبی بود، ان شاءالله با انرژی مسیرتون رو ادامه بدید.

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