angular - 带有反应形式的 Angular Mat-Table 在单击按钮时不显示数据,它会添加带有错误的空行
问题描述
在AddRow_click()上,我正在填充insuranceFormArray并将其值分配给datasource。但是在添加之后,我在表中添加了一个空行,我在控制台中也收到了以下错误消息。我只显示了其中一些错误,因为它们在我的 html 上的所有表单控件中重复出现。
保险组件.ts
import { Component, OnInit, Inject, ChangeDetectorRef, ɵConsole } from '@angular/core';
import { MatDialogRef, MatTableDataSource, MatPaginator, MAT_DIALOG_DATA, MatTable, MatSort } from '@angular/material';
import { trigger, state, style, transition, animate } from '@angular/animations';
import { AssetEntity } from 'src/app/model/proposal/asset-entity.moodel';
import { ProposalAssetInsurance } from 'src/app/model/proposal/proposal-asset-insurance.model';
import { userInfo } from 'os';
import { AppStorage } from 'src/app/core/appstorage';
import { SessionKeys } from 'src/app/core/SessionKeys';
import { ProposalEntity } from 'src/app/model/proposal/proposal-entity.model';
import { validateConfig } from '@angular/router/src/config';
import { forkJoin } from 'rxjs/internal/observable/forkJoin';
import { LookupService } from 'src/app/services/data-services/lookup.service';
import { FormControl, FormGroup, Validators, FormBuilder, FormArray } from '@angular/forms';
import { _MatTabHeaderMixinBase } from '@angular/material/tabs/typings/tab-header';
import { CurrencyIndex } from '@angular/common/src/i18n/locale_data';
@Component({
selector: 'app-insurance',
templateUrl: './insurance.component.html',
animations: [
trigger('detailExpand', [
state('collapsed', style({ height: '0px', minHeight: '0' })),
state('expanded', style({ height: '*' })),
transition('expanded <=> collapsed', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)')),
]),
],
styleUrls: ['./insurance.component.css']
})
export class InsuranceComponent implements OnInit{
displayedColumns = [ 'insuranceCategoryCode',
'insuranceCoverageTypeCode',
'insuranceTypeCode',
'insurer',
'policyNumber',
'insuredPerson',
'duration',
'currencyCode',
'insuredAmount',
'startDate',
'expiryDate',
'premiumAmount',
'commissionPct',
'componentFinanceTypeCode',
'marginRate',
'Delete'
];
assetIndex:number=0;
insurances : ProposalAssetInsurance[];
proposalEntity : ProposalEntity;
user = this.appStorage.getFromSession(SessionKeys[SessionKeys.USER]);
selectedIndex : number ;
InsuranceControl = new FormControl();
InsuranceCategories = [];
InsuranceCoverageTypes = [];
InsuranceTypes = [];
Insurers = [];
Currencies = [];
FinanceTypes =[];
insuranceFormGroup:FormGroup;
insuranceFormArray:FormArray;
dataSource = new MatTableDataSource<ProposalAssetInsurance>();
constructor( private fb: FormBuilder,
private cd: ChangeDetectorRef,
private appStorage: AppStorage,
private lookupService: LookupService,
private matRefDialog:MatDialogRef<InsuranceComponent>,@Inject(MAT_DIALOG_DATA) public data: any) { }
ngOnInit(){
this.insuranceFormArray = this.fb.array([]);
this.insuranceFormGroup = this.fb.group({
insuranceFormArray: [this.insuranceFormArray]
});
this.insurances = this.data.proposalEntity.ProposalArticleEntity[this.assetIndex].AssetEntity.ProposalAssetInsurances;
this.proposalEntity = this.data.proposalEntity;
var res = forkJoin(
{
InsuranceCategories: this.lookupService.GetInsuranceCategories(),
InsuranceCoverageTypes: this.lookupService.GetInsuranceCoverageTypes(),
InsuranceTypes: this.lookupService.GetInsuranceTypes(this.proposalEntity.Proposal.financialProductId),
Insurers: this.lookupService.GetInsuranceCompanies(),
Currencies : this.lookupService.GetCurrencies(),
FinanceTypes : this.lookupService.GetComponentFinanceTypes(),
}
);
res.subscribe(p => {
this.InsuranceCategories = p.InsuranceCategories.Payload;
this.InsuranceCoverageTypes = p.InsuranceCoverageTypes.Payload;
this.InsuranceTypes = p.InsuranceTypes.Payload;
this.Insurers = p.Insurers.Payload;
this.Currencies = p.Currencies.Payload;
this.FinanceTypes = p.FinanceTypes.Payload;
}
);
if(this.insurances)
{
for(let ins of this.insurances)
{
this.insuranceFormArray.push(this.initiateForm(ins));
}
}
this.dataSource.data = this.insuranceFormArray.value;
console.log("OnInit:"+this.insuranceFormArray.value);
}
initiateForm(ins:ProposalAssetInsurance): FormGroup {
return this.fb.group({
insuranceCategoryCode: [ins.insuranceCategoryCode , Validators.required],
insuranceCoverageTypeCode: [ins.insuranceCoverageTypeCode, Validators.required],
insuranceTypeCode: [ins.insuranceTypeCode, Validators.required],
insurer:[ins.insurer, Validators.required],
policyNumber: [ins.policyNumber, Validators.required],
insuredPerson: [ins.insuredPerson, Validators.required],
duration: [ins.duration, Validators.required],
currencyCode: [ins.currencyCode, Validators.required],
insuredAmount: [ins.insuredAmount, Validators.required],
startDate:[ins.startDate, Validators.required],
expiryDate: [ins.expiryDate, Validators.required],
premiumAmount: [ins.premiumAmount, Validators.required],
commissionPct:[ins.commissionPct, Validators.required],
componentFinanceTypeCode: [ins.componentFinanceTypeCode],
marginRate: [ins.marginRate, Validators.required]
});
}
DeleteRow_click(index:any)
{
this.insuranceFormArray.removeAt(index);
console.log("OnDelete:"+this.insuranceFormArray.value);
this.dataSource.data = this.insuranceFormArray.value;
this.cd.detectChanges();
}
AddRow_click(item: any)
{
if(!this.validate())
{
return;
}
var proposalAssetInsurance = new ProposalAssetInsurance();
proposalAssetInsurance.processingDate = this.user.processingDate;//new Date(this.user.processingDate);
proposalAssetInsurance.currencyCode = this.proposalEntity.Proposal.currencyCode;
proposalAssetInsurance.proposalId = this.proposalEntity.Proposal.proposalId;
proposalAssetInsurance.insuredAmount = this.proposalEntity.ProposalArticleEntity[this.assetIndex].AssetEntity.ProposalFinancialAgreement.assetAmount;
proposalAssetInsurance.duration = this.proposalEntity.ProposalArticleEntity[this.assetIndex].AssetEntity.ProposalFinancialAgreement.contractTerms;
proposalAssetInsurance.startDate = this.proposalEntity.ProposalArticleEntity[this.assetIndex].AssetEntity.ProposalFinancialAgreement.contractStartDate;
proposalAssetInsurance.marginRateInd = false;
proposalAssetInsurance.financeOptionEnableInd = true;
if (proposalAssetInsurance.startDate != null)
{
var expiry = this.proposalEntity.ProposalArticleEntity[this.assetIndex].AssetEntity.ProposalFinancialAgreement.contractStartDate;
// var years =proposalAssetInsurance.duration/12;
expiry.setFullYear(expiry.getFullYear() + 1);
expiry.setDate(expiry.getDate() - 1);
proposalAssetInsurance.expiryDate = expiry;
}
this.insuranceFormArray.push(this.initiateForm(proposalAssetInsurance));
console.log("OnAdd:"+this.insuranceFormArray.value);
this.dataSource.data = this.insuranceFormArray.value;
this.cd.detectChanges();
}
closeDialog()
{
this.matRefDialog.close();
}
openDetail(index:number)
{
//this.data.proposalEntity.ProposalArticleEntity[this.assetIndex].AssetEntity.ProposalRepaymentPlanEntity
}
validate():boolean
{
return true;
}
}
保险.component.html
<div class="dialog-header sticking-top-main" >
<h3><strong style="color: white !important;">Insurance</strong></h3>
<button mat-icon-button class="close-button" [mat-dialog-close]="true">
<mat-icon class="close-icon" [ngStyle]="{'color':'white'}">close</mat-icon>
</button>
</div>
<div class="row" style="width: 95%;margin-left: 40px;">
<button mat-icon-button matTooltip="Add row" (click)="AddRow_click($event)">
<i class="fa fa-plus fa-2x" style="color: var(--theme-color);"></i>
</button>
<button mat-icon-button matTooltip="Calculate" (click)="calculate_click($event)">
<i class="fa fa-calculator fa-2x" style="color: var(--theme-color);"></i>
</button>
</div>
<div [formGroup]="insuranceFormGroup" class="example-container mat-elevation-z8 scrollbar scrollbar-primary" style="height: 75%; width: 95%;">
<!-- table table-bordered -->
<mat-table #table [dataSource]="dataSource" style="width: fit-content;" formArrayName="insuranceFormArray">
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row;let i = index; columns: displayedColumns;" [formGroupName]="i"></mat-row>
<!-- insuranceCategoryCode Column -->
<ng-container matColumnDef="insuranceCategoryCode">
<mat-header-cell *matHeaderCellDef class="text-centre strong-700 sticking-top">
<div style="width: 100%;">Insurance Category</div>
</mat-header-cell>
<mat-cell class="text-centre" *matCellDef="let element; let i=index" >
<mat-select formControlName="insuranceCategoryCode">
<mat-option [value]="item.CODE" *ngFor="let item of InsuranceCategories">
{{ item.DESCRIPTION }}
</mat-option>
</mat-select>
</mat-cell>
</ng-container>
<!-- insuranceCoverageTypeCode Column -->
<ng-container matColumnDef="insuranceCoverageTypeCode">
<mat-header-cell *matHeaderCellDef class="text-centre strong-700 sticking-top">
<div style="width: 100%;">Insurance Coverage</div>
</mat-header-cell>
<mat-cell class="text-centre" *matCellDef="let element">
<mat-select formControlName="insuranceCoverageTypeCode">
<mat-option [value]="item.CODE" *ngFor="let item of InsuranceCoverageTypes">
{{ item.DESCRIPTION }}
</mat-option>
</mat-select>
</mat-cell>
</ng-container>
<!-- insuranceTypeCode Column -->
<ng-container matColumnDef="insuranceTypeCode">
<mat-header-cell *matHeaderCellDef class="text-centre strong-700 sticking-top">
<div style="width: 100%;">Insurance Type</div>
</mat-header-cell>
<mat-cell class="text-centre" *matCellDef="let element">
<mat-select formControlName="insuranceTypeCode">
<mat-option [value]="item.CODE" *ngFor="let item of InsuranceTypes">
{{ item.DESCRIPTION }}
</mat-option>
</mat-select>
</mat-cell>
</ng-container>
<!-- insurer Column -->
<ng-container matColumnDef="insurer">
<mat-header-cell *matHeaderCellDef class="text-centre strong-700 sticking-top">
<div style="width: 100%;">Insurer</div>
</mat-header-cell>
<mat-cell class="text-centre" *matCellDef="let element">
<mat-select formControlName="insurer">
<mat-option [value]="item.CODE" *ngFor="let item of Insurers">
{{ item.DESCRIPTION }}
</mat-option>
</mat-select>
</mat-cell>
</ng-container>
<!-- policyNumber Column -->
<ng-container matColumnDef="policyNumber">
<mat-header-cell *matHeaderCellDef class="text-centre strong-700 sticking-top">
<div style="width: 100%;">Policy Number</div>
</mat-header-cell>
<mat-cell class="text-centre" *matCellDef="let element">
<input matInput name="txtpolicyNumber" formControlName="policyNumber" > </mat-cell>
</ng-container>
<!-- insuredPerson Column -->
<ng-container matColumnDef="insuredPerson">
<mat-header-cell *matHeaderCellDef class="text-centre strong-700 sticking-top">
<div style="width: 100%;">Insured Person</div>
</mat-header-cell>
<mat-cell class="text-centre" *matCellDef="let element">
<input matInput name="insuredPerson" formControlName="insuredPerson" > </mat-cell>
</ng-container>
<!-- duration Column -->
<ng-container matColumnDef="duration">
<mat-header-cell *matHeaderCellDef class="text-centre strong-700 sticking-top">
<div style="width: 100%;">Duration</div>
</mat-header-cell>
<mat-cell class="text-centre" *matCellDef="let element">
<input matInput name="duration" formControlName="duration" > </mat-cell>
</ng-container>
<!-- currencyCode Column -->
<ng-container matColumnDef="currencyCode">
<mat-header-cell *matHeaderCellDef class="text-centre strong-700 sticking-top">
<div style="width: 100%;">Currency</div>
</mat-header-cell>
<mat-cell class="text-centre" *matCellDef="let element">
<mat-select formControlName="currencyCode">
<mat-option [value]="item.CODE" *ngFor="let item of Currencies">
{{ item.DESCRIPTION }}
</mat-option>
</mat-select>
</mat-cell>
</ng-container>
<!-- insuredAmount Column -->
<ng-container matColumnDef="insuredAmount">
<mat-header-cell *matHeaderCellDef class="text-centre strong-700 sticking-top">
<div style="width: 100%;">Insured Amount</div>
</mat-header-cell>
<mat-cell class="text-centre" *matCellDef="let element">
<input matInput name="insuredAmount" formControlName="insuredAmount" > </mat-cell>
</ng-container>
<!-- startDate Column -->
<ng-container matColumnDef="startDate">
<mat-header-cell *matHeaderCellDef class="text-centre strong-700 sticking-top">
<div style="width: 100%;">Start Date</div>
</mat-header-cell>
<mat-cell class="text-centre" *matCellDef="let element">
<input name="dtpStartDate" matInput
[matDatepicker]="StartDatePicker" formControlName="startDate"
(focus)="StartDatePicker.open()" >
<mat-datepicker #StartDatePicker></mat-datepicker>
</mat-cell>
</ng-container>
<!-- expiryDate Column -->
<ng-container matColumnDef="expiryDate">
<mat-header-cell *matHeaderCellDef class="text-centre strong-700 sticking-top">
<div style="width: 100%;">Expiry Date</div>
</mat-header-cell>
<mat-cell class="text-centre" *matCellDef="let element">
<input name="dtpexpiryDate" matInput
[matDatepicker]="expiryDatePicker" formControlName="expiryDate"
(focus)="expiryDatePicker.open()" >
<mat-datepicker #expiryDatePicker></mat-datepicker>
</mat-cell>
</ng-container>
<!-- premiumAmount Column -->
<ng-container matColumnDef="premiumAmount">
<mat-header-cell *matHeaderCellDef class="text-centre strong-700 sticking-top">
<div style="width: 100%;">Premium Amount</div>
</mat-header-cell>
<mat-cell class="text-centre" *matCellDef="let element">
<input matInput name="premiumAmount" formControlName="premiumAmount" > </mat-cell>
</ng-container>
<!-- commissionPct Column -->
<ng-container matColumnDef="commissionPct">
<mat-header-cell *matHeaderCellDef class="text-centre strong-700 sticking-top">
<div style="width: 100%;">Commission %</div>
</mat-header-cell>
<mat-cell class="text-centre" *matCellDef="let element">
<input matInput name="commissionPct" formControlName="commissionPct" > </mat-cell>
</ng-container>
<!-- componentFinanceTypeCode Column -->
<ng-container matColumnDef="componentFinanceTypeCode">
<mat-header-cell *matHeaderCellDef class="text-centre strong-700 sticking-top">
<div style="width: 100%;">Financed</div>
</mat-header-cell>
<mat-cell class="text-centre" *matCellDef="let element">
<mat-select formControlName="componentFinanceTypeCode">
<mat-option [value]="item.CODE" *ngFor="let item of FinanceTypes">
{{ item.DESCRIPTION }}
</mat-option>
</mat-select>
</mat-cell>
</ng-container>
<!-- marginRate Column -->
<ng-container matColumnDef="marginRate">
<mat-header-cell *matHeaderCellDef class="text-centre strong-700 sticking-top">
<div style="width: 100%;">Customer Rate</div>
</mat-header-cell>
<mat-cell class="text-centre" *matCellDef="let element">
<input matInput name="marginRate" formControlName="marginRate" > </mat-cell>
</ng-container>
<!-- Delete Column -->
<ng-container matColumnDef="Delete">
<mat-header-cell *matHeaderCellDef class="text-centre strong-700 sticking-top">
<div style="width: 100%;"></div>
</mat-header-cell>
<mat-cell class="text-centre" *matCellDef="let element;let i = index;">
<button mat-icon-button matTooltip="Delete" (click)="DeleteRow_click(i)">
<i class="fa fa-trash" style="color: var(--theme-color);"></i>
</button>
</mat-cell>
</ng-container>
</mat-table>
</div>
<div class="row" style="width: 95%;margin-left: 40px; font-size: 1.5vw;font-weight: bold;">
<label style="color: var(--theme-color);">Total Amount:</label>
<label style="text-decoration: underline;color: var(--theme-color);"> € 0.00 </label>
</div>
错误
InsuranceComponent.html:20 ERROR Error: Cannot find control with path: 'insuranceFormArray -> 0'
at _throwError (forms.js:2436)
at setUpFormContainer (forms.js:2408)
at FormGroupDirective.addFormGroup (forms.js:5806)
at FormGroupName.ngOnInit (forms.js:2590)
at checkAndUpdateDirectiveInline (core.js:24503)
at checkAndUpdateNodeInline (core.js:35163)
at checkAndUpdateNode (core.js:35102)
at debugCheckAndUpdateNode (core.js:36124)
at debugCheckDirectivesFn (core.js:36067)
at Object.eval [as updateDirectives] (InsuranceComponent.html:20)
View_InsuranceComponent_2 @ InsuranceComponent.html:19
InsuranceComponent.html:20 ERROR CONTEXT DebugContext_
View_InsuranceComponent_2 @ InsuranceComponent.html:19
InsuranceComponent.html:27 ERROR Error: Cannot find control with path: 'insuranceFormArray -> insuranceCategoryCode'
at _throwError (forms.js:2436)
at setUpControl (forms.js:2304)
at FormGroupDirective.addControl (forms.js:5776)
at FormControlName._setUpControl (forms.js:6408)
at FormControlName.ngOnChanges (forms.js:6331)
at checkAndUpdateDirectiveInline (core.js:24499)
at checkAndUpdateNodeInline (core.js:35163)
at checkAndUpdateNode (core.js:35102)
at debugCheckAndUpdateNode (core.js:36124)
at debugCheckDirectivesFn (core.js:36067)
View_InsuranceComponent_4 @ InsuranceComponent.html:26
InsuranceComponent.html:27 ERROR CONTEXT DebugContext_
View_InsuranceComponent_4 @ InsuranceComponent.html:26
InsuranceComponent.html:41 ERROR Error: Cannot find control with path: 'insuranceFormArray -> insuranceCoverageTypeCode'
解决方案
使用以下帮助解决了我的问题。堆栈闪电战。我刚刚在我的matCellDef中给出了FormGroup的相对索引,就像这样。希望它可以帮助寻找答案的人。
<ng-container matColumnDef="insuranceCategoryCode">
<mat-header-cell *matHeaderCellDef class="text-centre strong-700 sticking-top">
<div style="width: 100%;">Insurance Category</div>
</mat-header-cell>
<mat-cell class="text-centre" *matCellDef="let element; let i=index" [formGroup]="insuranceFormArray.at(i)" >
<mat-select name="insuranceCategoryCode" formControlName="insuranceCategoryCode">
<mat-option [value]="item.CODE" *ngFor="let item of InsuranceCategories">
{{ item.DESCRIPTION }}
</mat-option>
</mat-select>
</mat-cell>
</ng-container>
推荐阅读
- windows - Windows 沙盒不运行 .NET 应用程序
- kubernetes - 阻止 Kubernetes Ingress 重写 URL
- javascript - 看来我无法通过 AJAX 将 JSON 对象传递给我的 php 服务器
- java - JVM CodeCache 区域中存储了哪些编译后的代码
- react-native - 如何在不使用图像的情况下更改 MapView.Marker “SIZE”?
- python - 有没有办法定期保存您当前正在使用的 Simulink 文件?
- android - 尝试将 Google 帐户与新电话号码关联时出现 FirebaseAuthUserCollisionException
- ios - 在iOS中以特定时间间隔不断调用API时如何处理网络连接?
- excel - 停止 excel 自动将换行文本应用于复制的数据
- phpmyadmin - Can't Acces Mysql / Phpmyadmin with error "(HY000/1130): Host 'localhost' is not allowed to connect to this MariaDB server"