我正在用角度7创建一个反应形式,能够动态添加和删除表中的行。
我需要的是
在用户单击“添加”按钮后,我需要将在这些控件中输入的值添加到表中。
表格行应包含这些值以及最后一列中的删除按钮。
如何使用反应形式实现这一目标。
当前我的用户界面看起来像这样
<form [formGroup]="frmFirm" (ngSubmit)="onSubmit()">
<div *ngIf="FirmDetails && FirmDetails.Firm" class="card-body scrollClass" style="width:100%">
<div class="form-group row">
<label for="inputEmail" class="col-md-1 col-form-label header">Websites</label>
<div class="col-md-3">
<div *ngIf="!EditMode">{{FirmDetails.Websites}}</div>
</div>
</div>
</div>
</form>
组件
import { Component, Injectable, NgZone, ViewEncapsulation, ViewChild, Input } from '@angular/core';
import { OnInit } from '@angular/core';
import { FirmService } from '../services/firm.service';
import * as ClassicEditor from '@ckeditor/ckeditor5-build-classic';
import { CommonDataService} from '../services/common.data.service';
import {FormGroup, FormControl, FormBuilder} from '@angular/forms';
@Component({
selector: 'mgr-firm',
templateUrl: './firm.component.html'
})
export class FirmComponent implements OnInit {
private Error: string;
public FirmDetails: any;
public EditMode: boolean;
public Editor = ClassicEditor;
public EditorConfig : string;
public events: string[] = [];
@Input() FirmId: number;
DateFoundedDate: Date;
public frmFirm: FormGroup;
constructor( private _fb: FormBuilder, private firmService: FirmService, private commonDataService: CommonDataService) {
}
ngOnInit() {
this.getFirmDetails();
this.initializeFormModel();
}
initializeFormModel() {
this.frmFirm = this._fb.group({
firmName: [''],
shortName: [''],
alternateName: [''],
dateFounded: [''],
firmHistory: [''],
People: [''],
});
}
setFormValues(FirmDetails: any) {
this.frmFirm.patchValue({
firmName: FirmDetails.Firm.NAME,
shortName: FirmDetails.Firm.SHORT_NAME,
alternateName: FirmDetails.Firm.ALTERNATE_NAME,
dateFounded: FirmDetails.Firm.DATE_FOUNDED,
firmHistory: FirmDetails.Firm.HISTORY_HTML,
People: FirmDetails.People
});
}
getFirmDetails() {
if (this.FirmId != null) {
this.firmService.getFirmDetails(this.FirmId)
.subscribe(data => {
this.FirmDetails = data;
this.setFormValues(this.FirmDetails);
},
err => {
this.Error = 'An error has occurred. Please contact BSG';
},
() => {
});
}
}
get dateFoundedDate(): Date {
var dateString = this.FirmDetails.Firm.DATE_FOUNDED;
var seconds = parseInt(dateString.replace(/\/Date\(([0-9]+)[^+]\//i, "$1"));
var date = new Date(seconds);
return date;
}
saveManager() {
this.firmService.createFirm(this.FirmDetails)
.subscribe(data => {
this.getFirmDetails();
this.EditMode = !this.EditMode;
},
err => {
this.Error = 'An error has occurred. Please contact BSG';
},
() => {
});
}
dateFoundedChanged(dateFoundedDate: Date) {
this.DateFoundedDate = dateFoundedDate;
}
}
更新的用户界面
<div class="form-group row">
<label for="inputEmail" class="col-md-1 col-form-label header">Websites</label>
<div class="col-md-3">
<!-- <div *ngIf="!EditMode">{{FirmDetails.Websites[0].WEBSITE_URL}}</div> -->
<!-- <input *ngIf="EditMode" kendoTextBox [readonly]="false" class="form-control"
/> -->
<div formArrayName="websites"
*ngFor="let item of frmFirm.get('websites').controls; let i = index; let last = last">
<div [formGroupName]="i">
<input formControlName="websiteUrl" placeholder="Website Url">
<input formControlName="username" placeholder="User Name">
<input formControlName="password" placeholder="Password">
<button (click)="removeWebsite()">Remove Website</button>
<button (click)="addWebsite()" *ngIf="last">Add Website</button>
</div>
</div>
</div>
</div>
更新的组件
import { Component, Injectable, NgZone, ViewEncapsulation, ViewChild, Input } from '@angular/core';
import { OnInit } from '@angular/core';
import { FirmService } from '../services/firm.service';
import * as ClassicEditor from '@ckeditor/ckeditor5-build-classic';
import { CommonDataService} from '../services/common.data.service';
import {FormGroup, FormControl, FormBuilder, FormArray} from '@angular/forms';
@Component({
selector: 'mgr-firm',
templateUrl: './firm.component.html'
})
export class FirmComponent implements OnInit {
private Error: string;
public FirmDetails: any;
public EditMode: boolean;
public Editor = ClassicEditor;
public EditorConfig : string;
public events: string[] = [];
@Input() FirmId: number;
DateFoundedDate: Date;
public frmFirm: FormGroup;
constructor( private _fb: FormBuilder, private firmService: FirmService, private commonDataService: CommonDataService) {
}
ngOnInit() {
this.getFirmDetails();
this.initializeFormModel();
}
initializeFormModel() {
this.frmFirm = this._fb.group({
firmName: [''],
shortName: [''],
alternateName: [''],
dateFounded: [''],
firmHistory: [''],
People: [''],
websites: this._fb.array([
this.createWebsite()
])
});
}
// public addWebsite(): void {
// const websites = this.frmFirm.get('websites') as FormArray;
// websites.push(this._fb.control(''));
// }
public addWebsite(): void {
this.websites.push(this.createWebsite());
}
public removeWebsite(index: number): void {
const websites = this.frmFirm.get('websites') as FormArray;
websites.removeAt(index);
}
private createWebsite(): FormGroup {
return this._fb.group({
websiteUrl: [''],
username: [''],
password: ['']
});
}
get websites(): FormArray {
return <FormArray>this.frmFirm.get('websites');
}
setFormValues(FirmDetails: any) {
this.frmFirm.patchValue({
firmName: FirmDetails.Firm.NAME,
shortName: FirmDetails.Firm.SHORT_NAME,
alternateName: FirmDetails.Firm.ALTERNATE_NAME,
dateFounded: FirmDetails.Firm.DATE_FOUNDED,
firmHistory: FirmDetails.Firm.HISTORY_HTML,
People: FirmDetails.People
});
const websiteGroup = this._fb.group({
websiteUrl: FirmDetails.Websites[0].WEBSITE_URL,
username: FirmDetails.Websites[0].USERNAME,
password: FirmDetails.Websites[0].PASSWORD
});
this.frmFirm.setControl('websites', this._fb.array([websiteGroup]));
}
getFirmDetails() {
if (this.FirmId != null) {
this.firmService.getFirmDetails(this.FirmId)
.subscribe(data => {
this.FirmDetails = data;
this.setFormValues(this.FirmDetails);
},
err => {
this.Error = 'An error has occurred. Please contact BSG';
},
() => {
});
}
}
get dateFoundedDate(): Date {
var dateString = this.FirmDetails.Firm.DATE_FOUNDED;
var seconds = parseInt(dateString.replace(/\/Date\(([0-9]+)[^+]\//i, "$1"));
var date = new Date(seconds);
return date;
}
saveManager() {
this.firmService.createFirm(this.FirmDetails)
.subscribe(data => {
this.getFirmDetails();
this.EditMode = !this.EditMode;
},
err => {
this.Error = 'An error has occurred. Please contact BSG';
},
() => {
});
}
dateFoundedChanged(dateFoundedDate: Date) {
this.DateFoundedDate = dateFoundedDate;
}
}
答案 0 :(得分:1)
您要寻找的是FormArray
。
Angular文档用示例很好地解释了这些示例,这些示例涵盖了需要添加和删除表单组的用例(在您的情况下,该行将带有公司详细信息)。
https://angular.io/guide/reactive-forms#dynamic-controls-using-form-arrays
适合您的情况的示例。
模板
<div formArrayName="companies"
*ngFor="let item of form.get('companies').controls; let i = index; let last = last">
<div [formGroupName]="i">
<input formControlName="firmName" placeholder="Firm name">
<input formControlName="shortName" placeholder="Short name">
<input formControlName="alternateName" placeholder="Alternate name">
<input formControlName="dateFounded" placeholder="Founded">
<input formControlName="firmHistory" placeholder="History">
<input formControlName="People" placeholder="People">
<button (click)="removeCompany()">Remove company</button>
<button (click)="addCompany()" *ngIf="last">Add company</button>
</div>
</div>
组件
...
public form: FormGroup;
constructor(private formBuilder: FormBuilder) {}
ngOnInit(): void {
this.form = this.formBuilder.group({
companies: this.formBuilder.array([ this.createCompany() ])
});
}
public addCompany(): void {
const companies = this.form.get('companies') as FormArray;
companies.push(this.createItem());
}
public removeCompany(index: number): void {
const companies = this.form.get('companies') as FormArray;
companies.removeAt(index);
}
private createCompany(): FormGroup {
return this.formBuilder.group({
firmName: [''],
shortName: [''],
alternateName: [''],
dateFounded: [''],
firmHistory: [''],
People: [''],
});
}
...
答案 1 :(得分:0)
我有类似的东西,但是我将它们添加为“块”而不是“行”。点击“添加其他地址”按钮以添加另一个块。
我确定格式只是对布局进行的一些修改。
更具挑战性的部分是代码。要具有可重复的字段集,您需要使用一个FormArray,其中每个元素都是其自己的FormGroup。
我在这里有一个完整的示例:https://github.com/DeborahK/Angular-ReactiveForms/tree/master/Demo-Final
好吧,先前的答案使我难以置信……但是我将离开这个问题,同时该链接提供了一个完整的工作示例。