昨天調整mock-data有調整到檢核的部分
不過檢核的部分寫在Form-input好像也會讓這邊太複雜
而且為了方便日後管理與擴增
我們今天會多拆一個validator.service
import { Injectable } from '@angular/core';
import { ValidatorFn, Validators } from '@angular/forms';
@Injectable({
providedIn: 'root'
})
export class ValidatorService
{
constructor() { }
getValidators(validatorStrings: string[]): ValidatorFn[]
{
return validatorStrings.map((v: string) =>
{
let keyword = v.split(':')
switch (keyword[0])
{
case 'required':
return Validators.required;
case 'maxLength':
return Validators.maxLength(Number(keyword[1]));
default:
return null;
}
}
).filter(v => !!v) as ValidatorFn[]
}
}
我們把原本form-input的邏輯搬進來
這邊我們的概念是傳原本的字串陣列近來
然後傳ValidatorFn陣列出去
這個型別可以直接丟到addValidator裡面
// form-input.component.ts
if (setting.validator && setting.validator?.length > 0)
{
if (!!setting.validator.find(v => v == 'required')) setting.required = true;
newControl.addValidators(this.validatorService.getValidators(setting.validator))
}
然後這邊的話原本會另外設定required這個值
這邊在設定檔裡面就修改成不額外設定
如果validator裡面有required的時候就把fieldSetting裡面的required設為true
另外 我們也可能會有一些自定義的檢核的部分
也是可以寫在validator.service裡面
這邊想寫一個有點特別的自定義檢核
就是radioText元件裡面的
如果radio勾選true則text必填
這邊的邏輯我設計成
若這個欄位的parent之下的某個欄位為true則必填
這個某個欄位我可以從外面傳入
這樣關鍵字可以設定成像這樣
{
"name": "radioTextRadio1",
"cname": "控制輸入欄位",
"inputType": "radio",
"defaultValue": "true",
"groupName": "radioText1",
"groupType": "radioText-radio",
"options": [
{ "label": "是", "value": "true" },
{ "label": "否", "value": "false" }
]
},
{
"name": "radioTextText1",
"cname": "控制輸入欄位",
"inputType": "text",
"groupName": "radioText1",
"groupType": "radioText-text",
"placeholder": "勾選後才可輸入",
"defaultValue": "",
"validator": ["requiredTrueWithField:radioTextRadio1"] //新增特殊關鍵字
},
這樣validator.service裡面會長像這樣
getValidators(validatorStrings: string[]): ValidatorFn[]
{
return validatorStrings.map((v: string) =>
{
let keyword = v.split(':')
switch (keyword[0])
{
case 'required':
return Validators.required;
case 'maxLength':
return Validators.maxLength(Number(keyword[1]));
case 'requiredTrueWithField':
return this.requiredTrueWithField(keyword[1]);
default:
return null;
}
}
).filter(v => !!v) as ValidatorFn[]
}
requiredTrueWithField(fieldName: string): ValidatorFn
{
return (control: AbstractControl): { [key: string]: any } | null =>
{
if (!control.parent)
{
return null; // 如果 control 沒有 parent,則返回 null(暫時不驗證)
}
const fieldControl = control.parent.get(fieldName);
fieldControl?.valueChanges.pipe(distinctUntilChanged()).subscribe(r =>
{
control.updateValueAndValidity();
})
if (fieldControl && fieldControl.value == "true")
{
// 如果 A 為 true,B 必填
return Validators.required(control) ? { required: true } : null;
}
return null; // A 不是 true,B 無需必填
};
}
由於這個檢核是寫在text上
但我們需要radio異動的時候也要刷新狀態
所以我們要在這裡面對radio做監聽並處理
如果有其他想要新增的檢核 就可以通通在Validator.service裡面做處理
今日程式:day23