问题
i am trying to create nested forms but i am stuck in the second level and not sure how the addAttribute and removeAttribute will look like ?
export class ExportFormComponent implements OnInit {
public exportForm: FormGroup;
constructor( private formBuilder: FormBuilder ) { }
ngOnInit() {
this.exportForm = this.formBuilder.group( {
dataType: [''],
items: this.formBuilder.array( [
this.initItem(),
] )
});
}
initItem() {
return this.formBuilder.group( {
exportExpression: [''],
description: [''],
updatable: [true],
attributes: this.formBuilder.array( [
this.initAttribute(),
] )
});
}
initAttribute() {
return this.formBuilder.group( {
exportExpression: [''],
localizedRawField: [''],
localizable: [true],
});
}
addItem() {
const control = <FormArray>this.exportForm.controls['items'];
control.push( this.initItem() );
}
removeItem( i: number ) {
const control = <FormArray>this.exportForm.controls['items'];
control.removeAt( i );
}
addAttribute() {
}
removeAttribute( ) {
}
save( exportConfiguration: ExportConfiguration ) {
console.log( exportConfiguration );
}
}
My interface tree
export interface ExportConfiguration {
dataType?: string,
items?: Item[],
}
export interface Item {
exportExpression?: string,
description?: string,
updatable?: boolean,
attributes?: Attribute[],
}
export interface Attribute {
exportExpression?: string,
localizable?: boolean,
localizedRawField?: string,
rules?: TransformationRule[]
}
export interface TransformationRule {
dataPathKey?: string,
expressionCheck?: boolean,
expression?: string,
}
EDIT
Okay so i used the demo posted as one of the answers but i get null in the following ( this.itemsCtrl.get( '${index}.attributes' ) as FormArray )
addAttribute( index: number ) {
( this.itemsCtrl.get( '${index}.attributes' ) as FormArray ).push( this.initAttribute() );
}
回答1:
First of all I prefer to create references in component to handle the controls, instead of calling .controls
or .get
all the time.
So, your add
's and remove
's functions will be cleaner as your template.
It could be like this:
exportForm: FormGroup;
dataTypeCtrl: FormControl;
itemsCtrl: FormArray;
constructor(private formBuilder: FormBuilder) { }
ngOnInit() {
this.dataTypeCtrl = this.formBuilder.control('');
this.itemsCtrl = this.formBuilder.array([this.initItem()]);
this.exportForm = this.formBuilder.group( {
dataType: this.dataTypeCtrl,
items: this.itemsCtrl
});
}
// ...
addItem() {
this.itemsCtrl.push(this.initItem());
}
removeItem(i: number) {
this.itemsCtrl.removeAt(i);
}
addAttribute(index: number) {
this.itemsCtrl.get(`${index}.attributes`).push(this.initAttribute())
}
removeAttribute(itemIndex: number, attrIndex: number) {
this.itemsCtrl.get(`${itemIndex}.attributes`).removeAt(attrIndex)
}
Then, in template you can access directly the controls
, as below:
...
<div formArrayName="items" *ngFor="let itemCtrl of itemsCtrl.controls; let i = index">
<div [formGroupName]="i">
<button (click)="removeItem(i)">Remove item</button>
<input type="text" formControlName="description">
<!-- other inputs from items -->
<button (click)="addAttribute(i)">Add attribute</button>
<div formArrayName="attributes" *ngFor="let attributeCtrl of itemCtrl.get('attributes').controls; let j = index">
<div [formGroupName]="j">
<button (click)="removeAttribute(i, j)">Remove attribute</button>
<input type="text" formControlName="exportExpression"
<!-- other inputs from attributes -->
</div>
</div>
</div>
</div>
See DEMO
来源:https://stackoverflow.com/questions/42417698/angular2-create-model-nested-forms