اعتبارسنجی در فرم های دینامیک انگولار — از صفر تا صد
در این مقاله به بررسی یک رویکرد مناسب در مورد اعتبارسنجی دینامیک روی فرمهای واکنشی دینامیک انگولار میپردازیم. راه اندازی اعتبارسنجها به صورت درجا هنگام کار روی فرمهای دینامیک کار نسبتاً دشواری است، زیرا باید کد زیادی برای مدیریت این نوع از اشیا با فراخوانی متدهای setValidators و clearValidators در انگولار انجام دهیم، اما این پیچیدگی زمانی که با اعتبارسنجی شرطی مواجه میشویم و ماهیت دینامیک فرم از طریق منطق اعتبارسنجی سفارشی ما در کامپوننت از دست میرود، باز هم افزایش مییابد. در این مقاله به بررسی روش اعتبارسنجی دینامیک در فرمهای دینامیک انگولار میپردازیم.
رویکرد مناسب در این مورد کدام است؟
منطق بیزینس اعتبارسنجی و بخش فرم دینامیک در این رویکرد استاندارد ترکیب میشوند و احتمال بروز موارد کدهای تکراری در چندین کامپوننت بالا میرود. بهکارگیری اعتبارسنجی از طریق مدل دامنه به جای متد کامپوننت صورت میگیرد. مزیت این رویکرد آن است که کد جدا میشود و دیگر لازم نیست setValidators یا clearValidators را در کامپوننت فراخوانی کنیم.
اینک در مورد بخش چگونگی کار صحبت میکنیم. ابتدا باید چارچوب مورد خود را مشخص کنیم.
- firstName دینامیک مربوط به FormControl باید الزامی باشد و تنها مقادیر حرفی و فاصله را قبول کند.
- بدین ترتیب دیگر هیچ اعتبارسنجی نباید روی isAuthor FormControl اجرا شود. اعتبارسنجی ما بر اساس بررسی مقدار اجرا خواهد شد.
- اگر isAuthor انتخاب شده باشد، url دینامیک FormControl باید الزامی باشد.
- bio دینامیک FormControl باید بر مبنای منطق بیزینس سفارشی اعتبارسنجی شود. اگر مقدار isAuthor صحیح باشد، کاربر میتواند حداکثر 100 کاراکتر وارد کند، در غیر این صورت بیشینه 50 کاراکتر مجاز خواهد بود.
- مقدار userName دینامیک FormControl باید در اعتبارسنجی ناهمگام یکتا باشد.
مثالی از اعتبارسنجی دینامیک
اینک بدون این که وقت خود را هدر بدهیم، شروع به ساخت فرم دینامیک با اعتبارسنجی دینامیک میکنیم.
برای دستیابی به مثال فوق باید دو پکیج را به نامهای rxweb/reactive-dynamic-forms@ و rxweb/reactive-form-validators@ نصب کنیم. اگر در مورد این پکیجها چیزی نمیدانید میتوانید از این راهنما (+) استفاده کنید. با دستورهای زیر پکیجها را نصب کنید:
npm install @rxweb/reactive-dynamic-forms npm install @rxweb/reactive-form-validators
اینک باید ماژولهای RxReactiveDynamicFormsModule و RxReactiveFormsModule را در ماژول ریشه ثبت کنیم.
1import { NgModule } from '@angular/core';
2import { BrowserModule } from '@angular/platform-browser';
3
4import { FormsModule,ReactiveFormsModule } from '@angular/forms';
5
6import { RxReactiveDynamicFormsModule } from "@rxweb/reactive-dynamic-forms"
7import { RxReactiveFormsModule } from "@rxweb/reactive-form-validators"
8
9@NgModule({
10 imports: [ BrowserModule,
11 FormsModule,ReactiveFormsModule,
12 RxReactiveFormsModule,RxReactiveDynamicFormsModule
13 ],
14 declarations: [ ],
15 bootstrap: [ ]
16})
17export class AppModule { }
اینک JSON مثال را طراحی کرده و خروجی را مشاهده میکنیم. چنان که در نکته اول ابتدای مقاله اشاره کردیم، firstName دینامیک مربوط به FormControl باید الزامی باشد و تنها کاراکترهای حرفی و فاصله را بپذیرد.
1{
2 "type": "text",
3 "name": "firstName",
4 "validators": {
5 "required": true,
6 "alpha": { "allowWhiteSpace": true }
7 },
8 "ui": {
9 "label": "First Name",
10 "placeholder": "Enter Your First Name"
11 }
12}
چنان که در شیء JSON فوق میبینید، دو مشخصه درون مشخصه اعتبارسنجها تعریف کردهایم. مشخصه required موجب میشود FormControl به صورت الزامی علامتگذاری شود و alpha امکان وارد کردن کاراکترهای حرفی و فاصله را فراهم میسازد. بدین ترتیب اعتبارسنجها بدون نوشتن هرگونه کد اضافی در کامپوننت اعمال میشوند.
چه تعداد دیگری نام اعتبارسنج را میتوانیم در JSON ارسال کنیم؟
پکیج به صورت داخلی از rxweb/reactive-form-validators@ استفاده میکند. امکان استفاده از حدوداً 50 اعتبارسنج که در مستندات معرفی شدهاند وجود دارد. برای کسب اطلاعات بیشتر به این صفحه (+) مراجعه کنید.
بنا بر نیاز باید JSON را بدون نام اعتبارسنج تعریف کنیم.
1{
2 "type": "checkbox",
3 "name": "isAuthor",
4 "source": [
5 {
6 "value": true,
7 "text": "Is Author"
8 }
9 ]
10}
اینک نوبت به بررسی نکته سوم رسیده است. در این بخش یک مثال دیگر را بررسی میکنیم. یک JSON از url مربوط به FormControl دینامیک ایجاد کرده و conditionalExpression را برای FormControl الزامی به صورت شرطی تعیین میکنیم.
1{
2 "type": "text",
3 "name": "url",
4 "validators": {
5 "required": { "conditionalExpression": "x => x.isAuthor != null && x.isAuthor" }
6 },
7 "ui": {
8 "label": "Your Website Url",
9 "placeholder": "Enter Your site URL"
10 }
11}
در JSON فوق عبارت کد جاوا اسکریپت را به شکل رشته تعیین کردهایم. بدین ترتیب از مزیت تغییر عبارت شرطی در سمت سرور، به جای نوشتن کد در سمت کلاینت بهرهمند میشویم.
در مورد نکته چهارم که در ابتدای مقاله اشاره کردیم، اعتبارسنجی سفارشی باید مدل را ایجاد و متد اعتبارسنجی را نیز تعریف کند. اینک BioModel را میسازیم.
1import { AbstractControl } from "@angular/forms"
2import { FormControlConfig } from "@rxweb/reactive-dynamic-forms"
3
4export class BioModel extends FormControlConfig {
5 validator = (control: AbstractControl) => {
6 if(control.parent && control.value){
7 let isAuthor = control.parent.value.isAuthor;
8 if(isAuthor)
9 return control.value.length < 100 ? null : {
10 custom: { message: 'You can enter below 100 Characters.' }
11 }
12 else
13 return control.value.length < 50 ? null : {
14 custom: { message: 'You can enter below 50 Characters.' }
15 }
16 }
17 return null;
18 }
19}
چنان که در کد فوق میبینید، کار بسیار ساده است و متد اعتبارسنجی درون BioModel تعریف شده است. در کد زیر FormControl دینامیک به نام bio را میبینید:
1 {
2 "type": "textarea",
3 "name": "bio",
4 "modelName": "bio",
5 "ui": {
6 "label": "Bio",
7 "placeholder": "Describe about Yourself"
8 }
9}
مانند JSON فوق، modelName را برای اجرای اعتبارسنجی سفارشی خود تعریف کردیم. این همان BioModel است که در زمان ایجاد FormGroup استفاده میکنیم.
در مورد نکته پنجم ابتدای مقاله، باید ابتدا username را از طریق asyncValidator اعتبارسنجی کنیم. عمل دیگری را تعریف کرده و متد asyncValidator را ایجاد میکنیم.
1import { FormControlConfig } from "@rxweb/reactive-dynamic-forms";
2import { AbstractControl } from "@angular/forms"
3
4export class UserModel extends FormControlConfig {
5
6 asyncValidator = (control: AbstractControl) => {
7 let promise = new Promise<any>((resolve, reject) => {
8 if(control.value == "john")
9 resolve(null);
10 else
11 resolve({ required: {message:"Username should be unique."}})
12 });
13 return promise;
14 }
15
16}
فرایند کار دقیقاً همانند BioModel است، به جز این که این بار asyncValidator را تعریف میکنیم. به JSON زیر توجه کنید:
1{
2 "type": "text",
3 "name": "userName",
4 "modelName": "user",
5 "ui": {
6 "label": "User Name",
7 "placeholder": "Enter Your Username"
8 }
9}
اینک با ایجاد سریع کامپوننت و HTML مواردی که مطرح شد را جمعبندی کنیم. ابتدا باید modelName هر دو مدل را تعریف کنیم. modelName باید همان باشد که در شیء JSON متناظر تعریف شده است. سپس باید متد formGroup را با ارسال پارامتر پیکربندی فراخوانی کنیم.
1import { Component, OnInit } from '@angular/core';
2import { RxDynamicFormBuilder,DynamicFormBuildConfig,DynamicFormConfiguration } from "@rxweb/reactive-dynamic-forms"
3import { ReactiveFormConfig } from "@rxweb/reactive-form-validators"
4import { BioModel } from "./models/bio.model"
5import { UserModel } from "./models/user.model"
6import { SERVER_DATA } from "./server-data-json"
7
8@Component({
9 selector: 'my-app',
10 templateUrl: './app.component.html',
11})
12export class AppComponent implements OnInit {
13
14 serverData:any[] = SERVER_DATA;
15
16 dynamicForm:DynamicFormBuildConfig;
17 dynamicFormConfiguration:DynamicFormConfiguration;
18
19 constructor(private dynamicFormBuilder:RxDynamicFormBuilder){}
20
21 uiBindings:string[] = ["firstName","isAuthor","url","bio","userName"];
22
23 ngOnInit(){
24 this.dynamicFormConfiguration = {
25 controlConfigModels:[{modelName:"bio",model:BioModel},{modelName:"user",model:UserModel}]
26 }
27 this.dynamicForm = this.dynamicFormBuilder.formGroup(this.serverData,this.dynamicFormConfiguration)
28 }
29}
اکنون HTML را ایجاد میکنیم.
1<form [formGroup]="dynamicForm.formGroup">
2 <div viewMode="basic" [rxwebDynamicForm]="dynamicForm" [uiBindings]="uiBindings">
3 </div>
4 <button [disabled]="!dynamicForm.formGroup.valid" type="submit" class="btn btn-primary">Submit</button>
5</form>
بدین ترتیب کار به پایان میرسد. برای مشاهده کد کامل این پروژه میتوانید به این صفحه (+) مراجعه کنید. امیدواریم رویکرد مطرح شده در این مقاله مورد توجه شما قرار گرفته باشد.
اگر این مطلب برای شما مفید بوده است، آموزشهای زیر نیز به شما پیشنهاد میشوند:
- مجموعه آموزشهای JavaScript (جاوا اسکریپت)
- آموزش JavaScript ES6 (جاوا اسکریپت)
- مجموعه آموزشهای برنامهنویسی
- استفاده از وب کامپوننت در انگولار — به زبان ساده
- ساخت کتابخانه انگولار با Angular CLI — از صفر تا صد
==