關(guān)于angular表單動(dòng)態(tài)驗(yàn)證的一種新思路分享
引言
在項(xiàng)目中,我們有時(shí)候往往需要?jiǎng)颖韱蔚尿?yàn)證做動(dòng)態(tài)的規(guī)劃。比如在一個(gè)注冊(cè)界面中同步注冊(cè)兩種用戶,但兩種用戶的輸入項(xiàng)卻不是相同的。
教師的話,要求輸入工號(hào):
學(xué)生用戶的話,則要求輸入學(xué)號(hào):
我們把這種情景,稱為動(dòng)態(tài)的表單驗(yàn)證。
在上述表中校驗(yàn)中,我們要求:
- 工號(hào)與學(xué)號(hào)互不干擾。
- 選擇教師類型時(shí),只判斷工號(hào)是否已經(jīng)輸入。
- 選擇學(xué)生類型時(shí),則只判斷學(xué)號(hào)是否已經(jīng)輸入。
實(shí)現(xiàn)方案
其實(shí)這個(gè)實(shí)現(xiàn)的方案有很多種。在項(xiàng)目中我們已經(jīng)使用過的大體有三種:
- 使用跨字段驗(yàn)證器。
- 訂閱用戶類型,將用戶類型發(fā)生變化時(shí),重置工號(hào)或?qū)W號(hào)的驗(yàn)證規(guī)則。
- 訂閱用戶類型,將用戶類型發(fā)生變化時(shí),在fromGroup中添加或移除工號(hào),學(xué)號(hào)FromControl。
跨字段驗(yàn)證器
Anguar的官方給出在在跨字段驗(yàn)證器的使用示例,該思想是在FromGroup上添加一個(gè)驗(yàn)證器,然后在該驗(yàn)證器中獲取FormControl的值,在根據(jù)具體的情況來進(jìn)行驗(yàn)證。
優(yōu)點(diǎn):
- 官方示例,學(xué)習(xí)成本低。
- 直接將驗(yàn)證放到了驗(yàn)證器中,邏輯清晰。
- 驗(yàn)證器不會(huì)對(duì)獲取FromGroup的值產(chǎn)生影響。
缺點(diǎn):
- 無法在FormControl直接定義驗(yàn)證條件,不直觀。
- 只能統(tǒng)一顯示錯(cuò)誤信息,無法為單一的字段定制錯(cuò)誤信息。
你可以點(diǎn)擊https://segmentfault.com/a/1190000041563611來查看實(shí)現(xiàn)樣例。
重置驗(yàn)證規(guī)則
FromControl提供了clearValidators()
來清空驗(yàn)證器,以及setValidators()
來設(shè)置驗(yàn)證器,所以我們可以訂閱用戶類型是否發(fā)生變化,在發(fā)生變化時(shí),根據(jù)情況清空交叉字段的驗(yàn)證器,然后再重新對(duì)其驗(yàn)證器進(jìn)行設(shè)置。
優(yōu)點(diǎn):
- 為動(dòng)態(tài)地添加異步驗(yàn)證器提供了一種新的思路
缺點(diǎn):
- 驗(yàn)證規(guī)則不直觀。
- 代碼量大。
重置FromGroup項(xiàng)
FromGroup提供的removeControl()
使得我們可以移除其中的FormControl
,利用該機(jī)制我們可以訂閱用戶類型發(fā)生變化后,根據(jù)情況來移除、添加相應(yīng)的FormControl,從而達(dá)到動(dòng)態(tài)驗(yàn)證表單的目的。
示例代碼 C 層:
export class AppComponent implements OnInit { name = 'Angular ' + VERSION.major; formGroup = new FormGroup({}); // 學(xué)號(hào) studentNoFormControl = new FormControl(null, Validators.required); // 工號(hào) teachterNoFormControl = new FormControl(null, Validators.required); // 用戶類型 typeFormControl = new FormControl(null, Validators.required); ngOnInit(): void { this.formGroup.addControl('name', new FormControl('', Validators.required)); this.formGroup.addControl('type', this.typeFormControl); // 訂閱類型的變化,從而決定在formGroup中添加學(xué)號(hào)還是工號(hào)FormControl this.typeFormControl.valueChanges.subscribe((type) => { if (type === 0) { this.formGroup.removeControl('studentNo'); this.formGroup.addControl('teacherNo', this.teachterNoFormControl); } else { this.formGroup.removeControl('teacherNo'); this.formGroup.addControl('studentNo', this.studentNoFormControl); } }); // 初始化用戶類型為教師 this.typeFormControl.setValue(0); } onSubmit(): void { alert('submit'); } /** * 顯示學(xué)號(hào)或是工號(hào)的input */ showStudent(): boolean { return this.typeFormControl.value === 1; } }
V 層:
<hello name="{{ name }}"></hello> <p>表單動(dòng)態(tài)驗(yàn)證示例</p> <pre>{{ formGroup.invalid | json }}</pre> <pre>{{ formGroup.get('type').value | json }}</pre> <form [formGroup]="formGroup"> <div>姓名:<input type="text" formControlName="name" /></div> <div> 用戶類型: <label ><input type="radio" [value]="0" formControlName="type" name="type" /> 教師</label > <label ><input type="radio" [value]="1" formControlName="type" name="type" /> 學(xué)生</label > </div> <div *ngIf="showStudent()"> 學(xué)號(hào):<input type="text" formControlName="studentNo" /> </div> <div *ngIf="!showStudent()"> 工號(hào):<input type="text" formControlName="teacherNo" /> </div> <button [disabled]="formGroup.invalid" (click)="onSubmit()">Submit</button> </form>
優(yōu)點(diǎn):
- 直接在FormControl上設(shè)置驗(yàn)證器,代碼直觀。
- 可以直接使用angular提供的ngvalid等class屬性,快速定義校驗(yàn)結(jié)果的樣式。
缺點(diǎn):
- 驗(yàn)證器會(huì)對(duì)獲取FromGroup的值產(chǎn)生影響。比如在后續(xù)對(duì)FormGroup獲取相關(guān)的值的操作中,需要對(duì)FormGroup是否有值來進(jìn)行判斷,容易產(chǎn)生在undefined上調(diào)用value的錯(cuò)誤。(這可以使用?來規(guī)避 ----
formGroup.get('xxx')?.value
。
總結(jié)
到此這篇關(guān)于angular表單動(dòng)態(tài)驗(yàn)證的一種新思路的文章就介紹到這了,更多相關(guān)angular表單動(dòng)態(tài)驗(yàn)證內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
簡(jiǎn)單講解AngularJS的Routing路由的定義與使用
這篇文章主要介紹了AngularJS的Routing路由的定義與使用,講解了when()和otherwise()兩個(gè)相關(guān)的常用方法,需要的朋友可以參考下2016-03-03對(duì)angularJs中$sce服務(wù)安全顯示html文本的實(shí)例
今天小編就為大家分享一篇對(duì)angularJs中$sce服務(wù)安全顯示html文本的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-09-09angularjs 中$apply,$digest,$watch詳解
這篇文章主要介紹了angularjs 中$apply,$digest,$watch詳解的相關(guān)資料,需要的朋友可以參考下2016-10-10詳解angularJs模塊ui-router之狀態(tài)嵌套和視圖嵌套
這篇文章主要介紹了詳解angularJs模塊ui-router之狀態(tài)嵌套和視圖嵌套,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-04-04angular6.0使用教程之父組件通過url傳遞id給子組件的方法
這篇文章主要介紹了angular6.0使用教程之父組件通過url傳遞id給子組件的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-06-06使用Angular CLI進(jìn)行單元測(cè)試和E2E測(cè)試的方法
這篇文章主要介紹了使用Angular CLI進(jìn)行單元測(cè)試和E2E測(cè)試的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-03-03AngularJS 打開新的標(biāo)簽頁實(shí)現(xiàn)代碼
本文通過實(shí)例代碼給大家介紹了angularJS 打開新的標(biāo)簽頁方法,代碼簡(jiǎn)單易懂,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下吧2017-09-09

angular ngClick阻止冒泡使用默認(rèn)行為的方法