У меня есть компонент, который создает элемент управления формы с опциями «добавить другое поле» и «удалить это поле» на основе объекта шаблона.
Например, для этого шаблона:
assignmentLinkTemplateObj = {
name: 'Name',
url: 'URL'
}
должен создать 2 текстовых поля с именами полей 'name' и 'url' и местозаполнителями 'Name' и 'URL'. Теперь компонент добавляет эти поля одним нажатием кнопки «Добавить другое назначение». И удаляет комбинацию этих 2 полей при нажатии «удалить это назначение».
Аналогично, если шаблон:
pastTopicalLinkTemplateObj = {
name: 'Name',
type: ['ER', 'MS', 'GT', 'QP'],
url: 'URL'
}
Тип является массивом, поэтому компонент будет отображать раскрывающийся список со значениями этого массива.
Вот что я сделал:
Markup:
<form nz-form [formGroup]="validateForm">
<nz-form-item *ngFor="let control of controlArray; let i = index">
<nz-form-label [nzXs]="24" [nzSm]="6" *ngIf="i == 0" [nzFor]="control[field]">
<!-- RENDER DROPDOWNS OR TEXT FIELDS -->
<ng-container *ngFor="let field of objectKeys(fieldsTemplate)">
<nz-select *ngFor="let option of fieldsTemplate[field]" *ngIf="isObj(fieldsTemplate[field])">
<nz-option [nzLabel]="option" [nzValue]="option"></nz-option>
</nz-select>
<input
*ngIf="!isObj(fieldsTemplate[field])"
nz-input
style="margin-right:8px;"
[placeholder]="fieldsTemplate[field]"
[attr.id]="control.id"
[formControlName]="control['id']+control[field]"
/>
</ng-container>
<!-- REMOVE FIELD -->
<i nz-icon type="minus-circle-o" class="dynamic-delete-button" (click)="removeField(control['id'], $event)"></i>
</div>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-control [nzXs]="{ span: 24, offset: 0 }" [nzSm]="{ span: 20, offset: 6 }">
<!-- ADD ANOTHER FIELD -->
<button nz-button nzType="dashed" style="width:inherit;" (click)="addField($event)">
<i nz-icon type="plus"></i> Add
</button>
</nz-form-control>
</nz-form-item>
</form>
Component.ts:
validateForm: FormGroup;
@Input('name') name;
@Input('fieldsTemplate') fieldsTemplate;
@Input('error_text') error_text;
@Input('controlArray') controlArray: any = [];
@Output('valueAdd') valueAdd = new EventEmitter();
@Output('valueRemove') valueRemove = new EventEmitter();
objectKeys = Object.keys;
keys;
isObj(obj) {
return typeof obj == 'object';
}
addField(e ? : MouseEvent): void {
if (e) {
e.preventDefault();
}
const id = this.controlArray.length > 0 ? this.controlArray[this.controlArray.length - 1].id + 1 : 0;
this.keys = Object.keys(this.fieldsTemplate);
const control = {
id
};
this.keys.forEach(key => {
control[key] = key;
});
const index = this.controlArray.push(control);
this.keys.forEach(key => {
this.validateForm.addControl(
`${id}${this.controlArray[index - 1][key]}`,
new FormControl(null, Validators.required)
);
})
this.valueAdd.emit(this.controlArray);
}
removeField(id, e: MouseEvent): void {
e.preventDefault();
if (this.controlArray.length > 1) {
const index = this.getControlById(id);
this.controlArray.splice(index, 1);
this.keys.forEach(key => {
this.validateForm.removeControl(`${id}${this.controlArray[index - 1][key]}`);
});
this.valueRemove.emit(this.controlArray[index]);
}
}
getControlById(id) {
let index;
this.controlArray.filter((control, i) => {
if (control.id === id) {
index = i;
}
});
return index;
}
getFormControl(id: string): AbstractControl {
return this.validateForm.controls[this.getControlById(id)];
}
constructor(private fb: FormBuilder) {}
ngOnInit(): void {
this.validateForm = new FormGroup({
});
}
Проблема:
this.validateForm.value
теперь дает мне объект, похожий на этот:
{0name: "asd", 0url: "asd", 1name: "asd1", 1url: "asd2"}
Есть ли способ, которым я могу сделать это по-другому и сопоставить мои элементы управления формой с массивом объектов таким образом, чтобы каждая комбинация полей была объектом, а вся форма была массивом этих объектов.