我是Angular 2的新手,并决定学习最好的方法是通过Angular官方指南. 我浏览了“反应表单指南” https://angular.io/guide/reactive-forms 演示链接:https://stackblitz.com/angular/jammvmbrpxle 虽然内容总体来
我浏览了“反应表单指南”
https://angular.io/guide/reactive-forms
演示链接:https://stackblitz.com/angular/jammvmbrpxle
虽然内容总体来说非常好,但我仍然坚持如何实现更复杂的表单.在给定的示例中,每个Hero都有可能存在许多地址.地址本身就是一个扁平的对象.
如果地址有其他信息,例如位于地址的房间的颜色和类型,该怎么办?
export class Address { street = ''; city = ''; state = ''; zip = ''; rooms = Room[]; } export class Room { type = ''; }
这样表单模型看起来像这样……
createForm() { this.heroForm = this.fb.group({ name: '', secretLairs: this.fb.array([ this.fb.group({ street: '', city: '', state: '', zip: '', rooms: this.fb.array([ this.fb.group({ type: '' })]), })]), power: '', sidekick: '' });
}
编辑 – 与ngOnChanges一起使用的最终代码
英雄detail.component.ts
createForm() { this.heroForm = this.fb.group({ name: '', secretLairs: this.fb.array([ this.fb.group({ street: '', city: '', state: '', zip: '', rooms: this.fb.array([ this.fb.group({ type: '' }) ]) }) ]), power: '', sidekick: '' }); } ngOnChanges() { this.heroForm.reset({ name: this.hero.name, }); this.setAddresses(this.hero.addresses); } setAddresses(addresses: Address[]) { let control = this.fb.array([]); addresses.forEach(x => { control.push(this.fb.group({ street: x.street, city: x.city, state: x.state, zip: x.zip, rooms: this.setRooms(x) })) }) this.heroForm.setControl('secretLairs', control); } setRooms(x) { let arr = new FormArray([]) x.rooms.forEach(y => { arr.push(this.fb.group({ type: y.type })) }) return arr; }
hero-detail.component.html(嵌套表单数组部分)
<div formArrayName="secretLairs" class="well well-lg"> <div *ngFor="let address of heroForm.get('secretLairs').controls; let i=index" [formGroupName]="i" > <!-- The repeated address template --> <h4>Address #{{i + 1}}</h4> <div style="margin-left: 1em;"> <div class="form-group"> <label class="center-block">Street: <input class="form-control" formControlName="street"> </label> </div> <div class="form-group"> <label class="center-block">City: <input class="form-control" formControlName="city"> </label> </div> <div class="form-group"> <label class="center-block">State: <select class="form-control" formControlName="state"> <option *ngFor="let state of states" [value]="state">{{state}}</option> </select> </label> </div> <div class="form-group"> <label class="center-block">Zip Code: <input class="form-control" formControlName="zip"> </label> </div> </div> <br> <!-- End of the repeated address template --> <div formArrayName="rooms" class="well well-lg"> <div *ngFor="let room of address.get('rooms').controls; let j=index" [formGroupName]="j" > <h4>Room #{{j + 1}}</h4> <div class="form-group"> <label class="center-block">Type: <input class="form-control" formControlName="type"> </label> </div> </div> </div> </div> <button (click)="addLair()" type="button">Add a Secret Lair</button> </div>拥有嵌套的formarray并没有太大的不同.基本上你只需复制你拥有的代码……使用嵌套数组:)所以这是一个示例:
myForm: FormGroup; constructor(private fb: FormBuilder) { this.myForm = this.fb.group({ // you can also set initial formgroup inside if you like companies: this.fb.array([]) }) } addNewCompany() { let control = <FormArray>this.myForm.controls.companies; control.push( this.fb.group({ company: [''], // nested form array, you could also add a form group initially projects: this.fb.array([]) }) ) } deleteCompany(index) { let control = <FormArray>this.myForm.controls.companies; control.removeAt(index) }
这就是最外层表单数组的添加和删除,因此向嵌套表单数组添加和删除表单组只是复制代码.从模板中我们将当前表单组传递给您要添加的数组(在本例中)为新项目/删除项目.
addNewProject(control) { control.push( this.fb.group({ projectName: [''] })) } deleteProject(control, index) { control.removeAt(index) }
和模板以相同的方式,你迭代你的外部formarray,然后在里面迭代你的内部表单数组:
<form [formGroup]="myForm"> <div formArrayName="companies"> <div *ngFor="let comp of myForm.get('companies').controls; let i=index"> <h3>COMPANY {{i+1}}: </h3> <div [formGroupName]="i"> <input formControlName="company" /> <button (click)="deleteCompany(i)"> Delete Company </button> <div formArrayName="projects"> <div *ngFor="let project of comp.get('projects').controls; let j=index"> <h4>PROJECT {{j+1}}</h4> <div [formGroupName]="j"> <input formControlName="projectName" /> <button (click)="deleteProject(comp.controls.projects, j)"> Delete Project </button> </div> </div> <button (click)="addNewProject(comp.controls.projects)"> Add new Project </button> </div> </div> </div> </div>
DEMO
编辑:
要在拥有数据后为表单设置值,可以调用以下方法来迭代数据并将值设置为表单.在这种情况下,数据看起来像:
data = { companies: [ { company: "example comany", projects: [ { projectName: "example project", } ] } ] }
我们调用setCompanies为表单设置值:
setCompanies() { let control = <FormArray>this.myForm.controls.companies; this.data.companies.forEach(x => { control.push(this.fb.group({ company: x.company, projects: this.setProjects(x) })) }) } setProjects(x) { let arr = new FormArray([]) x.projects.forEach(y => { arr.push(this.fb.group({ projectName: y.projectName })) }) return arr; }