TypeError:无法读取 null 的属性“无效”-Angular Reactive Forms
2019-07-17
7607
我的 Angular 应用中有一个反应式表单,用于接收来自用户的 IP 地址范围。我使用反应式表单,以便用户可以随意输入和删除 IP 范围。
表单本身使用 FormBuilder 创建一个 FormArray,其中包含两个作为文本输入的表单控件。创建表单和每个表单数组元素的所有代码都相对简单。但是,似乎存在与在表单中显示验证错误有关的问题。具体来说,这些行
<mat-error *ngIf="endingRange.invalid">
<p>IP address is not valid.</p>
</mat-error>
如果我注释掉这些行,表单就可以正常工作,不会出现任何问题。但是,如果我取消注释这些行,则会开始出现以下错误:
TypeError: Cannot read property 'invalid' of null
这对我来说没有多大意义,因为我在组件文件中声明了此特定表单控件,如下所示
get endingRange() {
return this.ipRangeForm.get('endingRange');
}
另一个可能存在问题的方面是表单最初隐藏在视图中,并通过使用切换启用。我不确定这是否会导致错误,但值得一提。您可以在以下文件中看到此逻辑。
以下是正在使用的完整文件。
SettingsComponent
export class SettingsComponent implements OnInit {
ipRestrictionEnabled: boolean;
ipRangeForm: FormGroup;
constructor(
baseService: PageService, private formBuilder: FormBuilder
) {
super(baseService);
}
ngOnInit() {
this.ipRestrictionEnabled = false;
this.ipRangeForm = this.formBuilder.group(
{
ipRanges: this.formBuilder.array([])
}
);
}
ngOnDestroy() {
this.destroy$.next(true);
}
getPageConfig() {
return {
pageKey: 'settings',
displaySidebar: true,
displayToolbar: true,
backButtonRoute: ''
};
}
toggleIpRestriction(): void {
this.ipRestrictionEnabled = !this.ipRestrictionEnabled;
}
get ipRangeForms() {
return this.ipRangeForm.get('ipRanges') as FormArray;
}
addRange() {
const ipRange = this.formBuilder.group({
startingRange: ['',
[
Validators.required,
// tslint:disable-next-line:max-line-length
Validators.pattern('^(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])$')
]
],
endingRange: ['',
[
Validators.required,
// tslint:disable-next-line:max-line-length
Validators.pattern('^(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])$')
]
]
});
this.ipRangeForms.push(ipRange);
}
get startingRange() {
return this.ipRangeForm.get('ipRanges').get('startingRange');
}
get endingRange() {
return this.ipRangeForm.get('ipRanges').get('endingRange');
}
deleteRange(index) {
this.ipRangeForms.removeAt(index);
}
submitIpRanges() {
console.log(this.ipRangeForms.getRawValue());
}
>
SettingsComponent
<ng-container *ngIf="ipRestrictionEnabled">
<div class="row mt-xl">
<div class="col-12">
<h4>{{ getTranslateKey('ipRanges') | translate }}</h4>
<p>{{ getTranslateKey('ipRangesDescription') | translate }}</p>
</div>
</div>
<div class="row">
<div class="col-12">
<form [formGroup]="ipRangeForm">
<div formArrayName="ipRanges">
<div *ngFor="let ranges of ipRangeForms.controls; let i=index" [formGroupName]="i">
<div class="row mb-lg">
<div class="col-6">
<mat-card>
<div class="row">
<div class="col-5">
<mat-form-field style="width: 100%;">
<label>
<input matInput placeholder="{{ getTranslateKey('startingRange.label') | translate }}" value="" formControlName="startingRange">
</label>
<mat-error *ngIf="startingRange.invalid">
<p>IP address is not valid.</p>
</mat-error>
</mat-form-field>
</div>
<div class="col-5">
<mat-form-field style="width: 100%;">
<label>
<input matInput placeholder="{{ getTranslateKey('endingRange.label') | translate }}" value="" formControlName="endingRange">
</label>
<!-- <mat-error *ngIf="endingRange.invalid">-->
<!-- <p>IP address is not valid.</p>-->
<!-- </mat-error>-->
</mat-form-field>
</div>
<div class="col-2 remove-column">
<button swui-core-button (click)="deleteRange(i)" class="mr-sm pd-zero"
color="secondary" buttonStyle="link">
{{ getTranslateKey('remove') | translate }}
</button>
</div>
</div>
</mat-card>
</div>
</div>
</div>
</div>
</form>
</div>
</div>
<div class="row">
<div class="col-12">
<button swui-core-button (click)="addRange()" class="mr-sm" color="secondary" buttonStyle="link">
<mat-icon class="button-icon">add</mat-icon>
{{ getTranslateKey('addIP') | translate }}
</button>
</div>
</div>
</ng-container>
3个回答
用户表单数组名称
<mat-form-field style="width: 100%;">
<label>
<input matInput placeholder="{{ getTranslateKey('startingRange.label') | translate }}" value="" formControlName="startingRange">
</label>
<mat-error *ngIf="ranges.get('startingRange').invalid">
<p>IP address is not valid.</p>
</mat-error>
</mat-form-field>
MuruGan
2019-07-17
只需将
<mat-error *ngIf="endingRange.invalid">
<p>IP address is not valid.</p>
</mat-error>
更改为
<mat-error *ngIf="en​​dingRange && endingRange.invalid">
<p>IP 地址无效。</p>
</mat-error>
Baruch Gans
2019-07-17
endingRange 在 ipRangeForm 中不存在,它存在于 ipRanges 成员中。
this.ipRangeForm = this.formBuilder.group(
{
ipRanges: this.formBuilder.array([])
}
);
您需要将验证附加到每个 formArray 成员
Qellson
2019-07-17