您好,登錄后才能下訂單哦!
本篇內(nèi)容介紹了“Angular中的響應(yīng)式表單怎么用”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
1.FormControl 、FormArray 、FormGroup
1.FormControl: 用于追蹤單個(gè)表單控件的值和驗(yàn)證狀態(tài),例如一個(gè)欄位綁定
//初始化一個(gè)欄位的值為測(cè)試名字,并且不可用 const Name:FormControl = new FormControl({value:'測(cè)試名字', disabled: true });
2.FormArray:用于追蹤表單控件數(shù)組的值和狀態(tài),例如幾個(gè)欄位一起,常用的表格或者在表單中嵌入表格
//定義表單對(duì)象的屬性為aliases的FormArray this.validateForm = this.fb.group({aliases: this.fb.array([]),}); //獲取FormArray get aliases() {return this.validateForm.get('aliases') as FormArray;} //給FormArray 添加item this.aliases.push( this.fb.group({Id: 0,Name: [null],}) );
3.FormGroup:用于追蹤單個(gè)表單控件的值和驗(yàn)證狀態(tài),它可以包含單個(gè)或多個(gè)FormControl 和 FormArray ,一般一個(gè)表單對(duì)應(yīng)一個(gè)FormGroup實(shí)例,而表單的各個(gè)欄位對(duì)應(yīng)FormControl 和FormArray ,當(dāng)然他們可以互相嵌套,例如FormArray 中可以嵌套FormGroup,它的靈活性就是如此。
validateForm = new FormGroup({Name: new FormControl({value:'測(cè)試名字', disabled: true }),}); validateForm = this.fb.group({});
4.FormBuilder:是一個(gè)可注入的服務(wù)提供者,手動(dòng)創(chuàng)建多個(gè)表單控件實(shí)例會(huì)非常繁瑣,F(xiàn)ormBuilder 服務(wù)提供了一些便捷方法來(lái)生成表單控件,以前每一個(gè)創(chuàng)建要先生成FormGroup 然后生成FormControl,而使用FormBuilder的group方法可以減少重復(fù)代碼,說(shuō)白了就是幫助方便生成表單
validateForm!: FormGroup; //手動(dòng)創(chuàng)建 validateForm = new FormGroup({ Name: new FormControl('測(cè)試名字'), }); //FormBuilder表單構(gòu)建器 validateForm = this.fb.group({ Name:[ { value:'測(cè)試名字',disabled:true}], });
2.Validator 表單驗(yàn)證
表單驗(yàn)證用于確保用戶的輸入是完整和正確的。如何把單個(gè)驗(yàn)證器添加到表單控件中,以及如何顯示表單的整體狀態(tài),通常驗(yàn)證器返回null表示所有的驗(yàn)證通過(guò)。
1.同步驗(yàn)證器:同步驗(yàn)證器函數(shù)接受一個(gè)控件實(shí)例,然后返回一組驗(yàn)證錯(cuò)誤或 null
,在實(shí)例化FormControl 時(shí)可以將他作為第二個(gè)參數(shù)傳入
//formControlName的值必須和ts代碼中FormControl 的實(shí)例一致 <input type="text" id="name" class="form-control" formControlName="name" required> //判斷對(duì)應(yīng)的FormControl 是否沒(méi)通過(guò)校驗(yàn) 而有錯(cuò)誤信息 <div *ngIf="name.errors?.['required']"> Name is required. </div>
//初始化一個(gè)欄位并且加入必填校驗(yàn)驗(yàn)證器 const name:FormControl = new FormControl({'測(cè)試名字', disabled: true },Validators.required,); //獲取這個(gè)FormControl get name() { return this.heroForm.get('name'); }
2.異步驗(yàn)證器:異步函數(shù)接受一個(gè)控件實(shí)例并返回一個(gè) Promise 或 Observable ,只有在所有同步驗(yàn)證器都通過(guò)之后,Angular 才會(huì)運(yùn)行異步驗(yàn)證器,在實(shí)例化FormControl 時(shí)可以將他作為第三個(gè)參數(shù)傳入
3.內(nèi)置驗(yàn)證器:例如驗(yàn)證一些長(zhǎng)度,不能為空可以使用已經(jīng)提供的Validator 類來(lái)實(shí)現(xiàn)
4.自定義驗(yàn)證器:系統(tǒng)內(nèi)部提供的驗(yàn)證器不能滿足現(xiàn)有需求,可以使用自定義驗(yàn)證器做一些個(gè)性化的校驗(yàn),自定義校驗(yàn)器必須返回ValidationErrors類型或者空
//formControlName的值必須和ts代碼中FormControl 的實(shí)例一致 <input type="text" id="name" class="form-control" formControlName="name" required> //判斷對(duì)應(yīng)的FormControl 是否沒(méi)通過(guò)校驗(yàn) 而有錯(cuò)誤信息 <div *ngIf="name.hasError('Invalid')"> 名字也太長(zhǎng)了吧.... </div>
//初始化一個(gè)欄位并且加入必填校驗(yàn)驗(yàn)證器 const name:FormControl = new FormControl({'測(cè)試名字', disabled: true },this.CustomValidators()); CustomValidators() { return (control: AbstractControl): ValidationErrors | null => { if(control.value.length!=10) { return {Invalid:true} } return null; }; }
3.表單及元素的基本方法和屬性
方法
方法 | 使用效果 |
---|---|
setValue() | 使用setVlue可以設(shè)置控件FormControl 的值,但是使用時(shí)必須FormGroup所有的屬性一起賦值,不能單個(gè)賦值,常用在修改加載賦值。 |
patchValue() | 使用patchValue也可以設(shè)置FormControl的值,可以根據(jù)需要設(shè)置指定的FormControl,而不需要全部設(shè)置,常用在更新某個(gè)字段值 |
reset () | FormControl 中使用重置當(dāng)前控件所有狀態(tài),F(xiàn)ormGroup中使用就是重置表單對(duì)象里的內(nèi)容,例如控件被設(shè)為不可用disabled,control.reset({ value: 'Drew', disabled: true }); |
markAsPristine() | 是將表單控件值標(biāo)記為未改變,這個(gè)方法主要用在表單重置時(shí),此時(shí)它的狀態(tài)pristine為true |
markAsDirty() | 是將表單FormControl 控件值標(biāo)記為已改變,此時(shí)它的狀態(tài)Dirty為true |
updateValueAndValidity() | 重新計(jì)算表單FormControl 控件的值和驗(yàn)證狀態(tài)等 |
setValidators() | 給表單FormControl 控件設(shè)置驗(yàn)證器,如果設(shè)置多個(gè)就用數(shù)組"setValidators([v1,v2,v3])" |
disable() | 給表單FormControl 控件設(shè)置不可用,注意當(dāng)FormControl 是disabled時(shí),表單的常規(guī)取值getValue()對(duì)應(yīng)值會(huì)為空,可用getRawValue()取原始值對(duì)象得到對(duì)應(yīng)FormControl 的值 |
enable() | 給表單FormControl 控件設(shè)置啟用 |
屬性
屬性 | 使用方法說(shuō)明 |
---|---|
touched | 當(dāng)表單FormControl 控件 的touched為true表示控件已經(jīng)被獲取焦點(diǎn),反之同理 |
untouched | 當(dāng)untouched 為true表示控件未被獲取焦點(diǎn),反之同理 |
pristine | 表示表單元素是純凈的,用戶未操作過(guò),可以使用markAsPristine方法設(shè)為true |
dirty | 表示表單元素是已被用戶操作過(guò),可以使用markAsDirty方法設(shè)為true |
status | 獲取表單FormControl 控件上的的狀態(tài) |
Errors | 獲取當(dāng)前控件的錯(cuò)誤信息 |
1. 簡(jiǎn)單的表單實(shí)現(xiàn)
######需求1
我們主要用到的框架版本是Angular 12 + NG-ZORRO, 所以在下面很多實(shí)現(xiàn)和示例代碼將與他們有關(guān),雖然可能代碼不一樣,但也只是在UI層面的區(qū)別稍微大一點(diǎn)點(diǎn),但對(duì)于TS代碼,只是換湯不換藥,稍微注意一下就好了,其實(shí)下面實(shí)例中的需求,基本就是我在工作時(shí)需要做的的一些基本內(nèi)容和遇到的問(wèn)題,經(jīng)過(guò)查閱資料后解決的思路和過(guò)程,甚至截圖都一模一樣。
實(shí)現(xiàn)最基本的表單新增功能并且校驗(yàn)員工ID為必填以及長(zhǎng)度不能超過(guò)50,要實(shí)現(xiàn)的效果圖如下
分析
1.首先需求未提出有特殊注意點(diǎn),基本都是簡(jiǎn)單的輸入框賦值然后保存,只要基本的概念搞清楚實(shí)現(xiàn)這種最簡(jiǎn)單
2.我們用一個(gè)FormGroup和6個(gè)FormControl 完成和界面綁定即可
3.綁定驗(yàn)證器用于校驗(yàn)長(zhǎng)度和必填
實(shí)現(xiàn)步驟
1.定義html 表單結(jié)構(gòu)
<!-- formGroup 屬性綁定表單對(duì)象 --> <form nz-form [formGroup]="validateForm" nzLayout="vertical"> <nz-form-label nzRequired>Employee ID </nz-form-label> <!-- Employee_ErrorTrip為驗(yàn)證不通過(guò)彈出的提示信息 --> <!-- formControlName綁定表單元素FormControl --> <nz-form-control [nzErrorTip]="Employee_ErrorTrip"> <input nz-input formControlName="EmployeeID" placeholder="" /> </nz-form-control> <ng-template #Employee_ErrorTrip let-control> <ng-container *ngIf="control.hasError('required')"> 員工編號(hào)為必填項(xiàng)目 </ng-container> </ng-template> </form>
2.在TypeScript代碼中聲明表單對(duì)象,在構(gòu)造函數(shù)中注入FormBuilder,并且在ngOnInit中進(jìn)行表單初始化
//定義表單對(duì)象 validateForm:FormGroup; //構(gòu)造函數(shù)注入FormBuilder constructor(private fb: FormBuilder){} //在聲明周期鉤子函數(shù)中初始化表單 ngOnInit() { //初始化并且綁定必填驗(yàn)證器和長(zhǎng)度驗(yàn)證器 this.validateForm = this.fb.group({ EmployeeID: ['', [Validators.required, Validators.maxLength(50)]], }) }
2.在表格中應(yīng)用表單
需求2
需要實(shí)現(xiàn)表格的表單新增和提交以及個(gè)性化定制需求,要實(shí)現(xiàn)的效果圖和需求描述如下
1.點(diǎn)擊Add 添加一行表格 ,編輯完畢,點(diǎn)擊Save保存數(shù)據(jù),點(diǎn)擊Revoke取消編輯
2.默認(rèn)開(kāi)始時(shí)間和結(jié)束時(shí)間禁止使用
3.當(dāng)選擇Contract Type為 “短期合同” Contract start date 和Contract end date可用,當(dāng)選擇Contract Type為 “長(zhǎng)期合同”不可用
4.如果Contract start date 和Contract end date可用,需要驗(yàn)證開(kāi)始結(jié)束時(shí)間合法性,例如開(kāi)始事件不能超過(guò)結(jié)束時(shí)間
分析
1.在表格中使用表單,雖然表單在表格中,但是他的每一列同樣都是一個(gè)個(gè)FormControl
2.一共4列需要輸入值,就說(shuō)明有4個(gè)FormControl 然后最后一列就是2個(gè)按鈕
3.我們根據(jù)上面的基礎(chǔ)知識(shí)知道,F(xiàn)ormControl 不能單獨(dú)使用,所以需要被FormGroup包裹,此時(shí)說(shuō)明一行對(duì)應(yīng)一個(gè)FormGroup
4.由一行對(duì)應(yīng)一個(gè)FormGroup知道,我們的表格時(shí)多行的,也就是有多個(gè)FormGroup,我們可以使用FormArray來(lái)存儲(chǔ),因?yàn)樗硪唤M表單組
5.根據(jù)需求第2點(diǎn)默認(rèn)開(kāi)始時(shí)間和結(jié)束時(shí)間禁止使用,我們知道在一開(kāi)始初始化時(shí),設(shè)置開(kāi)始結(jié)束時(shí)間對(duì)應(yīng)的FormControl 為disabled就行了
6.第3點(diǎn)需求需要涉及聯(lián)動(dòng),也就是當(dāng)Contract Type對(duì)應(yīng)的FormControl 的值為“短期合同”時(shí),需要將 “開(kāi)始結(jié)束時(shí)間”對(duì)應(yīng)的FormControl設(shè)置為可用,這個(gè)需要自定義驗(yàn)證器來(lái)完成
實(shí)現(xiàn)步驟
1.首先定義Html表單結(jié)構(gòu)
<nz-table [nzData]="CONTRACTS" nzTableLayout="fixed" [nzShowQuickJumper]="true"> <thead> <tr> <th>Contract type</th> <th>Contract start date</th> <th>Contract end date</th> <th>Agreement item</th> <th>Operation</th> </tr> </thead> <tbody> <!-- 綁定表單組屬性aliases --> <ng-container formArrayName="aliases"> <!-- 將表單組中當(dāng)前行的索引與formGroup綁定 --> <tr [formGroupName]="i" *ngFor="let data of aliases.controls;index as i"> <td> <nz-form-item> <nz-form-control nzSpan="1-24"> <!-- AccountName綁定FormControl --> <nz-select nzShowSearch nzAllowClear nzPlaceHolder="" formControlName="Type"> <nz-option *ngFor="let option of Type" [nzValue]="option.Code" [nzLabel]="option.Value"> </nz-option> </nz-select> </nz-form-control> </nz-form-item> <nz-form-item> <nz-form-control nzSpan="1-24" [nzErrorTip]="StartDate"> <nz-date-picker id="StartDate" formControlName="StartDate" nzPlaceHolder=""> </nz-date-picker> <!-- 校驗(yàn)提示模板用于時(shí)間驗(yàn)證器 --> <ng-template #StartDate let-control> <!-- 判斷時(shí)間驗(yàn)證器是否存在beginGtendDate屬性,如果有說(shuō)明沒(méi)有通過(guò)驗(yàn)證 然后展示提示信息 --> <ng-container *ngIf="control.hasError('beginGtendDate')"> 開(kāi)始時(shí)間不能晚于結(jié)束時(shí)間 </ng-container> </ng-template> </nz-form-control> </nz-form-item> <nz-form-item> <nz-form-control nzSpan="1-24" [nzErrorTip]="EndDate"> <nz-date-picker style="width: 100%;" formControlName="EndDate" nzPlaceHolder=""> </nz-date-picker> <ng-template #EndDate let-control> <ng-container *ngIf="control.hasError('beginGtendDate')"> 開(kāi)始時(shí)間不能晚于結(jié)束時(shí)間 </ng-container> </ng-template> </nz-form-control> </nz-form-item> <nz-form-item> <nz-form-control nzSpan="1-24"> <nz-select nzShowSearch nzAllowClear nzPlaceHolder="" formControlName="ContractType"> <nz-option *ngFor="let option of ContractTypes" [nzValue]="option.Code" [nzLabel]="option.Value"> </nz-option> </nz-select> </nz-form-control> </nz-form-item> </td> <td> <button style="color: #009688;" nz-button nzType="text"> <i nz-icon nzType="save"></i>Save </button> <button nz-button nzType="text" nzDanger> <i nz-icon nzType="redo"></i>Revoke </button> </td> </tr> </ng-container> </tbody> </nz-table>
2.在TypeScript代碼中聲明表單對(duì)象validateForm,然后初始化一個(gè)FormArray類型的屬性aliases的實(shí)例作為表格formArrayName的值
3.點(diǎn)擊Add按鈕時(shí)向表單對(duì)象validateForm的屬性aliases添加一條數(shù)據(jù)
4.定義Contract Type 聯(lián)動(dòng)的自定義校驗(yàn)器 contractTypeValidation()方法
5.定義時(shí)間校驗(yàn)器 timeValidation()方法,如果時(shí)間不合法,將FormControl的錯(cuò)誤狀態(tài)設(shè)置屬性beginGtendDate,然后在模板中根據(jù)這個(gè)屬性來(lái)選擇是否渲染日式信息
//定義表單對(duì)象 validateForm:FormGroup; //構(gòu)造函數(shù)注入FormBuilder constructor(private fb: FormBuilder){} //在聲明周期鉤子函數(shù)中初始化一個(gè)表單對(duì)象validateForm ngOnInit() { this.validateForm = this.fb.group({ aliases: this.fb.array([]), }); } //聲明aliases屬性用作界面formArrayName綁定 get aliases(){ return this.validateForm.get('aliases') as FormArray; } addNewRow() { const group = this.fb.group({ //添加給Type初始化驗(yàn)證器 Type: [null, [CommonValidators.required, this.contractTypeValidation()]], //初始化禁用StartDate和EndDate的FormControl StartDate: [{ value: null, disabled: true }, []], EndDate: [{ value: null, disabled: true },[]], ContractType: [null, [CommonValidators.required, CommonValidators.maxLength(20)]], }) this.aliases.push(group); } //自定義Contract Type驗(yàn)證器 contractTypeValidation() { return (control: AbstractControl): ValidationErrors | null => { let contents: any[] = this.validateForm.value.aliases; if (control.touched && !control.pristine) { //獲取表單組 const formArray: any = this.validateForm.controls.aliases; //找到正在編輯的行的索引 const index = contents.findIndex((x) => !x.isShowEdit); //獲取開(kāi)始結(jié)束時(shí)間FormControl 實(shí)例 const StartDate: AbstractControl = formArray.controls[index].get('StartDate'), EndDate: AbstractControl = formArray.controls[index].get('EndDate'); if (control.value === "短期合同") { //給開(kāi)始結(jié)束時(shí)間設(shè)置驗(yàn)證器用于驗(yàn)證時(shí)間合法性 StartDate.setValidators([CommonValidators.required, this.timeValidation()]); EndDate.setValidators([this.timeValidation()]); //啟動(dòng)開(kāi)始結(jié)束時(shí)間控件 EndDate.enable(); StartDate.enable(); } else { //Contract Type不是短期合同就清除驗(yàn)證器 StartDate.clearValidators(); EndDate.clearValidators(); //禁用開(kāi)始結(jié)束時(shí)間 EndDate.disable(); StartDate.disable(); } } return null; } } //自定義時(shí)間驗(yàn)證器 timeValidation() { return (control: AbstractControl): ValidationErrors | null => { if (!control.pristine) { let contents: any[] = this.validateForm.value.aliases; const formArray: any = this.validateForm.controls.aliases; const index = contents.findIndex((x) => !x.isShowEdit); //獲取開(kāi)始結(jié)束時(shí)間FormControl實(shí)例 const EndDate: string = formArray.controls[index].get('EndDate').value; const StartDate: string =formArray.controls[index].get('StartDate').value; if (EndDate === null || StartDate === null) return null; //如果時(shí)間不合法,那就設(shè)置當(dāng)前控件的錯(cuò)誤狀態(tài) beginGtendDate為true if ( Date.parse(control.value) > Date.parse(EndDate) || Date.parse(control.value) < Date.parse(StartDate) ) { return { beginGtendDate: true }; } } return null; } }
“Angular中的響應(yīng)式表單怎么用”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。