Html Angular 4:如何对来自后端的数据使用自定义验证器
在表单中,只有当表单有效时,“提交”按钮才变为“启用”。特定的输入包含带有后端数据的datalist。如果用户填写的数据不在数据列表中,我想返回无效的表单。所以,我需要一个自定义验证器来检查用户数据是否等于来自后端的数据。 后端数据是包含参考号和其他数据的对象列表 因此,我尝试在同一组件文件中为自定义验证器创建一个函数,但由于以下两个原因,该函数不起作用:Html Angular 4:如何对来自后端的数据使用自定义验证器,html,angular,typescript,Html,Angular,Typescript,在表单中,只有当表单有效时,“提交”按钮才变为“启用”。特定的输入包含带有后端数据的datalist。如果用户填写的数据不在数据列表中,我想返回无效的表单。所以,我需要一个自定义验证器来检查用户数据是否等于来自后端的数据。 后端数据是包含参考号和其他数据的对象列表 因此,我尝试在同一组件文件中为自定义验证器创建一个函数,但由于以下两个原因,该函数不起作用: 我不知道如何检索我的物品列表“refere.refNumber.input”的路径 我在控制台中遇到错误:“无法读取未定义的属性'leng
- 我不知道如何检索我的物品列表“refere.refNumber.input”的路径
- 我在控制台中遇到错误:“无法读取未定义的属性'length'
export function ValidateRefNumber(control: AbstractControl) {
for (let refer of ArbologistiqueComponent.listOfArticles) {
if (control.value == refer.refNumber.input) {
return true;
}
}
return null;
}
我的整个组件。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;
}
<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>
从'@angular/core'导入{Component,OnInit};
导入'rxjs/add/operator/switchMap';
从“./management-arbologistique.service”导入{ManagementArbologistiqueService};
从“@angular/router”导入{ActivatedRoute,Params};
从“@angular/forms”导入{FormGroup、FormControl、FormBuilder、FormArray、Validators};
@组成部分({
选择器:“应用程序arbologistique”,
templateUrl:'./arbologistique.component.html',
样式URL:['./arbologistique.component.css']
})
导出类ArbologistiqueComponent实现OnInit{
私有responsetest:字符串;
私有物品列表:数组
私人路径下载:任何;
私有myFormGroup:FormGroup;
fileToUpload:File=null;
private ButtonsSubmitEnabled:boolean=false;
构造函数(公共fb:FormBuilder,私有managementArbo:ManagementArbologistiqueService,私有路由:ActivatedRoute){}
恩戈尼尼特(){
this.myFormGroup=this.fb.group({
itemRows:this.fb.array([this.initItemRows()]))
})
this.myFormGroup.valueChanges.subscribe(x=>this.buttonSubmitEnabled=false);
这是getListBdd();
}
initItemRows(){
返回此.fb.group({
…//其他字段
参考编号:['',[Validators.required,ValidateRefNumber]],
…//其他字段
})
}
addRow(索引:编号){
log(“调用functionAddRow”);
const control=this.myFormGroup.controls['itemRows'];
insert(索引,this.initItemRows());
}
deleteRow(索引:编号){
log(“调用functionDeleteRow”);
const control=this.myFormGroup.controls['itemRows'];
控制。移除(索引);
}
sendForm(){
this.buttonSubmitEnabled=true;
log(“functionExportCalled”);
this.route.params.subscribe((params:params)=>{
let subcure=“导出”;
this.managementArbo.postProducts(子例程,JSON.stringify(this.myFormGroup.value))
.订阅(
res=>{this.reponseTest=res;console.log('reponse:'+res);}
,
err=>console.log(err),
()=>console.log('getProducts done');
});
}
getListBdd(){
this.route.params.subscribe((params:params)=>{
let subcute=“getRefNumber”;
this.managementArbo.getProducts(子例程)
.订阅(
res=>{this.listOfArticles=res;console.log('response:'+res);}
,
err=>console.log(err),
()=>console.log('getProducts done');
});
}
获取refNb(){
返回此.myFormGroup.get('itemRows.refNb');
}
}
导出函数ValidateRefNumber(控件:AbstractControl){
对于(请参阅ArbologistiqueComponent.listOfArticles){
if(control.value==refere.refNumber.input){
返回true;
}
}
返回null;
}
使用数据列表(component.html)输入:
{{ref.refNumber.input}
我将用一个简单的示例为您提供答案,然后您可以根据需要对其进行转换。
假设我们有以下文章列表:
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>
因此,我们有一个formGroup,其中包含对required的简单验证,我们的新验证器名为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 }
这是控件的错误,因此您可以使用与访问required或minlength或任何其他错误相同的“matched”来访问此错误。
我希望它足够清楚,并给你一个很好的开端,以解决你的一点更复杂的问题 --更新--
更清楚地说:
findIndex在数组中搜索与条件匹配的第一个项,并返回该项的索引,如果没有找到,则返回-1。在本例中,我检查了用户输入的值是否与列表中的任何ID匹配。因此,只要我的res不等于-1,这意味着我找到了一个匹配的项,因此验证通过,但如果res==-1,则存在错误,因此我发送了一个新对象,该对象具有匹配的错误名称,以便您以后可以处理它。无论如何,在本例中,我没有找到任何与id匹配的项,因此这是一个错误 --更新2--
您遇到了一些问题,因此我提供了一个工作示例。
我将用一个简单的示例为您提供答案,然后您可以根据需要对其进行转换。
假设我们有以下文章列表:
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>
因此,我们有一个formGroup,其中包含对required的简单验证,我们的新验证器名为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。如果我找不到,我会退回一个obje