在 Angular 2 中,如何迭代 ControlGroup 数组并引用组中的控件?
ControlGroup 和 ControlArray plnkr 示例创建一个(空)城市Control
数组:
ctrlCities: Control[] = [
new Control(''),
new Control(''),
new Control('')
];
将它们包裹在ControlArray
中:
citiesArray: ControlArray = new ControlArray(this.ctrlCities);
并将它们分配给ControlGroup
形式,citites
:
formGroup: ControlGroup = new ControlGroup({
name: new ControlGroup({
first: this.ctrlFirst,
middle: this.ctrlMiddle,
last: this.ctrlLast
}),
food: this.ctrlFood,
cities: this.citiesArray
});
然后 HTML 迭代表单ControlGroup
:
<form [ng-form-model]="formGroup">
和cities
ControlGroup
:
<ul ng-control-group="cities">
最后处理 Control
数组中的每个Control
:
<li *ng-for="#ctrl of ctrlCities; #i = index"><input ng-control="{{i}}"></li>
如果城市控制器是一个组,我将如何引用该组中的控制?
大概,我会补充
ngControlGroup="{{i}}"
到我的块,然后在该块中引用组的各个控件,但这会导致我的应用程序中出现以下情况:
angular2.dev.js:23597 Error: Cannot find control '0'
at new BaseException (angular2.dev.js:7464)
at _throwError (angular2.dev.js:20733)
at Object.setUpControlGroup (angular2.dev.js:20726)
at NgFormModel.addControlGroup (angular2.dev.js:16863)
at NgControlGroup.ngOnInit (angular2.dev.js:16708)
at AbstractChangeDetector.ChangeDetector_MarketplaceAddComponent_7.detectChangesInRecordsInternal (viewFactory_MarketplaceAddComponent:2800)
at AbstractChangeDetector.detectChangesInRecords (angular2.dev.js:8156)
at AbstractChangeDetector.runDetectChanges (angular2.dev.js:8139)
at AbstractChangeDetector._detectChangesContentChildren (angular2.dev.js:8212)
at AbstractChangeDetector.runDetectChanges (angular2.dev.js:8140)
任何想法如何做到这一点?
旁白:控制 API 有点笨拙:在控制器中,新的Control
被push
到ControlArray
( citiesArray
),但在视图中,我们迭代了 Control
的数组 ( ctrlCities
)。为什么不是一个或另一个?
解决方案的更新 plnkr; 控制器被修改为使用具有name
和size
控件的每个城市的组:
ctrlCities: ControlGroup[] = [
new ControlGroup({'name':new Control(''),'size':new Control('')}),
new ControlGroup({'name':new Control(''),'size':new Control('')}),
new ControlGroup({'name':new Control(''),'size':new Control('')})
];
视图集组在div
数组中,然后直接引用name
和size
:
<ul ng-control-group="cities">
<li *ng-for="#ctrl of ctrlCities; #i = index">
<div ng-control-group="{{i}}">
<input ng-control="name"> <input ng-control="size">
</div>
</li>
</ul>
我在使用@angular2-material和ng2-material时遇到了同样的问题,以便利用md-messages(来自ng2-material)的使用,并能够通过编写更少的html代码自动显示错误。
在浪费了几个小时之后,我终于明白了如何将 ControlArray 与 ControlGroup 一起使用。
启发了自己以下的 plunkr: http://plnkr.co/edit/23DESOpbNnBpBHZt1BR4?p=preview
要理解的关键点是,您始终需要在表单构建器定义中定义的控制组中嵌套字段,即使它是控制数组。
我做了一个plunkr来展示如何使用它:http://plnkr.co/edit/QX6mjoVNd7ZopsGzmKk7
//our root app component
import {Component} from "@angular/core";
import {
Control,
ControlGroup,
ControlArray,
FORM_DIRECTIVES,
FormBuilder,
Validators
} from '@angular/common';
import {MATERIAL_DIRECTIVES} from "ng2-material/index";
import {MD_INPUT_DIRECTIVES} from "@angular2-material/input";
@Component({
selector: 'my-app',
providers: [],
directives: [MATERIAL_DIRECTIVES, MD_INPUT_DIRECTIVES]
template: `
<md-card>
<form name="setProfileForm" [ngFormModel]="setProfileForm">
<md-card-content>
<h2>Curriculum vitae</h2>
<div ngControlGroup="profileInfos">
<h3>About you</h3>
<div class="md-input-container">
<md-input #firstName="ngForm" ngControl="firstName" type="text" placeholder="Firstname"></md-input>
<div [md-messages]="firstName" role="alert">
<div md-message="required">Please provide a Firstname!</div>
</div>
</div>
<div class="md-input-container">
<md-input #lastName="ngForm" ngControl="lastName" type="text" placeholder="Lastname"></md-input>
<div [md-messages]="lastName" role="alert">
<div md-message="required">Please provide a Lastname!</div>
</div>
</div>
<div ngControlGroup="positions">
<h3>Your job positions</h3>
<div *ngFor="let controlGroup of positionsControlGroup; let i = index" ngControlGroup="{{i}}">
<h4>Position #{{i+1}}</h4>
<div class="md-input-container">
<md-input #company="ngForm" ngControl="company" type="text" placeholder="Company"></md-input>
<div [md-messages]="company" role="alert">
<div md-message="required">Please provide a Company!</div>
</div>
</div>
<div class="md-input-container">
<md-input #title="ngForm" ngControl="title" type="text" placeholder="Title"></md-input>
<div [md-messages]="title" role="alert">
<div md-message="required">Please provide a Title!</div>
</div>
</div>
</div>
</div>
</div>
<md-card-actions>
<button type="submit" md-button md-raised-button class="md-primary" [disabled]="!setProfileForm.valid">Submit</button>
</md-card-actions>
</md-card-content>
</form>
</md-card>
`
})
export class App {
setProfileForm:ControlGroup;
positionsControlGroup:ControlGroup[];
positionsControlArray:ControlArray;
constructor(public fb: FormBuilder) {
this.positionsControlGroup = [
fb.group({
company: fb.control(null, Validators.required),
title: fb.control(null, Validators.required)
}),
fb.group({
company: fb.control(null, Validators.required),
title: fb.control(null, Validators.required)
})
];
this.positionsControlArray = fb.array(this.positionsControlGroup);
this.setProfileForm = fb.group({
profileInfos: fb.group({
firstName: fb.control(null, Validators.required),
lastName: fb.control(null, Validators.required),
positions: this.positionsControlArray
})
});
}
}