我在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
导出类SettingsComponent实现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>
答案 0 :(得分:2)
用户表单数组名称
lbl_geheel.Text += node.InnerText;
答案 1 :(得分:0)
只是改变
<mat-error *ngIf="endingRange.invalid">
<p>IP address is not valid.</p>
</mat-error>
到
<mat-error *ngIf="endingRange && endingRange.invalid">
<p>IP address is not valid.</p>
</mat-error>
答案 2 :(得分:0)
结尾范围在ipRangeForm上不存在,它存在于ipRanges成员上。
this.ipRangeForm = this.formBuilder.group(
{
ipRanges: this.formBuilder.array([])
}
);
您需要将验证附加到每个formArray成员
答案 3 :(得分:0)
我认为在第一次get
调用和formGroup
初始化之间存在很小的延迟。
忽略那个;只需问问问号endingRange
。
<mat-error *ngIf="endingRange?.invalid">
<p>IP address is not valid.</p>
</mat-error>
因此,这将在检查endingRange
属性之前对invalid
进行角度检查。
答案 4 :(得分:0)
问题是您正在访问ipRanges,就好像它不是数组一样。 Angular无法知道您想要终止范围的数组中的哪个IP范围。尝试以下方法:
getEndingRange(idx:number) {
return this.ipRangeForms.controls[idx].get(‘endingRange’);
}
然后在模板中,将索引输入到函数中。
<mat-error *ngIf="getEndingRange(i).invalid">
对开始范围进行相同操作