angular學(xué)習(xí)之動態(tài)創(chuàng)建表單的方法
準備工作
使用ng new async-form創(chuàng)建一個新工程,在app.module.ts中引入ReactiveFormsModule模塊并在根模塊中導(dǎo)入
import { ReactiveFormsModule } from '@angular/forms';
@NgModule({
imports: [
ReactiveFormsModule
]
})
構(gòu)建表單元素的基類
export class QuestionBase<T> {
value: T;//表單元素的值
key: string;//表單元素鍵的名稱
label: string;//輸入元素的標題
required: boolean;//是否必輸
order: number;//排序
controlType: string;//表單的類型 選擇框/文本輸入框
constructor(options: {
value?: T,
key?: string,
label?: string,
required?: boolean,
order?: number,
controlType?: string
} = {}) {
this.value = options.value;
this.key = options.key || '';
this.label = options.label || '';
this.required = !!options.required;
this.order = options.order === undefined ? 1 : options.order;
this.controlType = options.controlType || '';
}
}
繼承表單元素的基類
選擇框元素的數(shù)據(jù)類型繼承基類,設(shè)置了controlType 為'dropdown'并新增了屬性options數(shù)組
import { QuestionBase } from './question-base';
export class QuestionDropdown extends QuestionBase<string>{
controlType = "dropdown";
options: { key: string, value: string }[] = [];
constructor(options: {} = {}) {
super(options);
this.options = options["options"] || [];
}
}
文本輸入框元素的數(shù)據(jù)類型繼承了基類,設(shè)置了controlType 為'textbox',新增了type屬性,定義input的類型
import { QuestionBase } from './question-base';
export class QuestionTextbox extends QuestionBase<string> {
controlType = "textbox";
type:string;
constructor(options:{} ={}){
super(options);
this.type = options["type"]||""
}
}
生成數(shù)據(jù)
根據(jù)表單元素的派生類生成表單的數(shù)據(jù)??梢砸胍粋€服務(wù)類,提供表單數(shù)據(jù)。
getQuestions(){
let questions:QuestionBase<any>[]=[
new QuestionDropdown({
key:'brave',
label:'Bravery Rating',
options:[
{key:'solid',value:'Solid'},
{key:'great',value:'Great'},
{key:'good',value:'Good'},
{key:'unproven',value:'Unproven'}
],
order:3
}),
new QuestionTextbox({
key:'firstName',
label:'First name',
value:"Bombasto",
required:true,
order:1
}),
new QuestionTextbox({
key:'emailAddress',
label:"Email",
type:'email',
order:2
})
];
return questions.sort((a, b) => a.order - b.order);
}
將數(shù)據(jù)轉(zhuǎn)成FormControl類型
可以專門提供一個服務(wù)類,將表單的數(shù)據(jù)轉(zhuǎn)成FormControl類型
toFormGroup(questions: QuestionBase<any>[]) {
let group: any = {};
questions.forEach(question => {
group[question.key] = question.required?new FormControl(question.value||"",Validators.required)
:new FormControl(question.value||"");
});
return new FormGroup(group);
}
到這里就已經(jīng)完整構(gòu)建出一組FormControl 實例了。
為數(shù)據(jù)提供頁面模板
<div [formGroup]="form">
<label [attr.for]="question.key">{{question.label}}</label>
<div [ngSwitch]="question.controlType">
<input *ngSwitchCase="'textbox'" [formControlName]= "question.key"
[id]="question.key" [type]="question.type">
<select [id]="question.key" *ngSwitchCase="'dropdown'"
[formControlName]="question.key">
<option *ngFor="let opt of question.options" [value]="opt.key">
{{opt.value}}
</option>
</select>
</div>
<div class="errorMessage" *ngIf="!isValid">
{{question.label}} is required
</div>
</div>
通過formGroup指令綁定表單數(shù)據(jù),ngSwitch指令來選擇生成的模板,formControlName指令綁定對應(yīng)的表單數(shù)據(jù)的key值
import { Component, OnInit, Input } from '@angular/core';
import {FormGroup} from '@angular/forms';
import {QuestionBase} from '../question-base';
@Component({
selector: 'app-dynamic-form-question',
templateUrl: './dynamic-form-question.component.html',
styleUrls: ['./dynamic-form-question.component.less']
})
export class DynamicFormQuestionComponent implements OnInit {
@Input() question:QuestionBase<any>;
@Input() form :FormGroup;
get isValid(){
return this.form.controls[this.question.key].valid;
}
constructor() { }
ngOnInit() {
}
}
表單組件需要兩個輸入,form和question,form來獲取對應(yīng)表單的鍵值是否校驗成功,question來渲染對應(yīng)表單輸入元素。使用app-dynamic-form-question標簽來使用組件
引用表單組件
<div *ngFor="let question of questions" class="form-row"> <app-dynamic-form-question [question]="question" [form]="form"></app-dynamic-form-question> </div>
獲取到questions數(shù)據(jù)后,通過*ngFor指令來渲染單個表單組件。
結(jié)束
到這里就完成了動態(tài)創(chuàng)建表單的功能,以這種方式來創(chuàng)建表單,我們只需要開始時構(gòu)建出指定的單個輸入框或者其他表單元素的樣式之后,通過改變數(shù)據(jù)來控制表單的內(nèi)容,便于后期維護。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Angular directive遞歸實現(xiàn)目錄樹結(jié)構(gòu)代碼實例
本篇文章主要介紹了Angular directive遞歸實現(xiàn)目錄樹結(jié)構(gòu)代碼實例,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-05-05
AngularJS雙向數(shù)據(jù)綁定原理之$watch、$apply和$digest的應(yīng)用
這篇文章主要介紹了AngularJS雙向數(shù)據(jù)綁定原理之$watch、$apply和$digest的應(yīng)用,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-01-01
AngularJS ng-bind 指令簡單實現(xiàn)
本文主要介紹AngularJS ng-bind 指令,在這里對ng-bind 指令做了詳細資料整理并講解,提供了實例代碼以便大家參考,有需要的小伙伴可以參考下2016-07-07
淺談Angularjs link和compile的使用區(qū)別
下面小編就為大家?guī)硪黄獪\談Angularjs link和compile的使用區(qū)別。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-10-10

