在表单中,仅当表单有效时,按钮提交才变为启用状态。特定的输入包含带有后端数据的数据列表。如果用户填写的数据不在数据列表中,我想返回无效的表格。所以,我需要一个自定义的验证器,它检查用户数据是否等于来自后端的数据。 来自后端的数据是对象 listOfArticles 的列表,其中包含参考编号和其他数据。
因此,我尝试在同一组件文件中为自定义验证器创建一个函数,但是由于两个原因,它不起作用:
我不知道如何检索我的 listOfArticles 的路径“ refer.refNumber.input ”
我在控制台中遇到错误:“无法读取未定义的属性'length'”。
自定义验证程序的功能:
export function ValidateRefNumber(control: AbstractControl) {
for (let refer of ArbologistiqueComponent.listOfArticles) {
if (control.value == refer.refNumber.input) {
return true;
}
}
return null;
}
我的整个 component.ts :
import { Component, OnInit } from '@angular/core';
import 'rxjs/add/operator/switchMap';
import { ManagementArbologistiqueService } from "../management-arbologistique.service";
import { ActivatedRoute, Params } from '@angular/router';
import { FormGroup, FormControl, FormBuilder, FormArray, Validators } from '@angular/forms';
@Component({
selector: 'app-arbologistique',
templateUrl: './arbologistique.component.html',
styleUrls: ['./arbologistique.component.css']
})
export class ArbologistiqueComponent implements OnInit {
private reponseTest: String;
private listOfArticles :Array<Object>
private pathDownload: any;
private myFormGroup: FormGroup;
fileToUpload: File = null;
private buttonSubmitEnabled: boolean = false;
constructor(public fb: FormBuilder, private managementArbo: ManagementArbologistiqueService, private route: ActivatedRoute) { }
ngOnInit() {
this.myFormGroup = this.fb.group({
itemRows: this.fb.array([this.initItemRows()])
})
this.myFormGroup.valueChanges.subscribe(x => this.buttonSubmitEnabled = false);
this.getListBdd();
}
initItemRows() {
return this.fb.group({
... //other fields
refNb: ['',[Validators.required, ValidateRefNumber]],
... //other fields
})
}
addRow(index: number) {
console.log("functionAddRow called");
const control = <FormArray>this.myFormGroup.controls['itemRows'];
control.insert(index, this.initItemRows());
}
deleteRow(index: number) {
console.log("functionDeleteRow called");
const control = <FormArray>this.myFormGroup.controls['itemRows'];
control.removeAt(index);
}
sendForm() {
this.buttonSubmitEnabled=true;
console.log("functionExportCalled");
this.route.params.subscribe((params: Params) => {
let subroute = "exportation";
this.managementArbo.postProducts(subroute, JSON.stringify(this.myFormGroup.value))
.subscribe(
res => { this.reponseTest = res; console.log('reponse:' + res); }
,
err => console.log(err),
() => console.log('getProducts done'));
});
}
getListBdd() {
this.route.params.subscribe((params: Params) => {
let subroute = "getRefNumber";
this.managementArbo.getProducts(subroute)
.subscribe(
res => { this.listOfArticles = res; console.log('reponse:' + res); }
,
err => console.log(err),
() => console.log('getProducts done'));
});
}
get refNb() {
return this.myFormGroup.get('itemRows.refNb');
}
}
export function ValidateRefNumber(control: AbstractControl) {
for (let refer of ArbologistiqueComponent.listOfArticles) {
if (control.value == refer.refNumber.input) {
return true;
}
}
return null;
}
输入数据列表( component.html ):
<input list="refNumbers" formControlName="refNb" type="text" name="article" maxlength="8" size="15" required title="8 characters" />
<datalist id="refNumbers">
<option *ngFor="let ref of listOfArticles">{{ref.refNumber.input}}</option>
</datalist>
答案 0 :(得分:1)
我将为您提供一个简单示例的答案,然后您可以根据需要对其进行转换。
可以说我们有以下文章列表:
articles = [
{
id: 1,
content: "test 123"
},
{
id: 2,
content: "test 345"
}
];
我们要检查用户是否在输入文本中输入文章ID之一,否则表单无效。
我们有这小段HTML:
<div *ngFor="let article of articles">
{{article | json}}
</div>
<form [formGroup]="cForm" (submit)="submitForm(cForm.value)" novalidate>
<input formControlName="article" type="text" name="article" required />
<input type="submit" value="submit" [disabled]="!cForm.valid">
</form>
因此,我只打印数组进行调试,并且我们输入了具有formFormName的文章。并且我们有一个按钮,如果表单无效,该按钮将被禁用。
初始化formGroup:
this.cForm = this._fb.group({
article: [
null,
Validators.compose([Validators.required, matchValues(this.articles)])
]
});
因此,我们有一个formGroup,其中包含对必填项的简单验证,还有一个名为matchValues的新验证器。
export const matchValues = (valuesToCheck: any[]): ValidatorFn => {
return (control: AbstractControl): { [key: string]: boolean } => {
const controlValue = control.value;
let res = valuesToCheck.findIndex(el => el.id === +controlValue);
console.log(res);
return res !== -1 ? null : { matched: true };
};
};
我只是将其包装在一个接收文章数组的函数中,并且我试图找到与输入文本的值匹配的文章ID。如果找不到任何内容,则返回一个对象:
{ matched: true }
这是控件的错误,因此您可以“匹配”来访问此错误,与访问必需或最小长度或任何其他错误相同。
我希望它足够清楚,可以为您解决一些更复杂的问题提供一个良好的开端。
-更新-
为了更清楚一点:
findIndex在数组中搜索与条件匹配的第一个项目,并返回该项目的索引;如果找不到任何内容,则返回-1;在这种情况下,我已经检查了用户输入的值是否与列表中的任何ID匹配。只要我的res不等于-1,那意味着我找到了一个匹配的项目,因此验证通过,但是如果res === -1则出现错误,所以我发送了错误名称匹配的新对象所以您以后可以处理。无论如何,在这种情况下,我找不到与ID匹配的任何项目,因此它是错误的。
-UPDATE2-
您遇到了一些麻烦,因此我提供了一个有效的示例。
Check this out