Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/29.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Angular 4验证器可同时检查2个控件_Angular_Angular Reactive Forms_Angular Validation - Fatal编程技术网

Angular 4验证器可同时检查2个控件

Angular 4验证器可同时检查2个控件,angular,angular-reactive-forms,angular-validation,Angular,Angular Reactive Forms,Angular Validation,我有一个带有两个控件(port_start和port_end)的反应式表单,具有以下要求: 两者都必须有一个值 它们的值必须介于0和65535之间 端口\u开始值必须小于端口\u结束值 这就是我迄今为止所尝试的: [...] this.formModel.addControl('port_start', new FormControl(object.port_start ? object.port_start : 0, [Validators.required, Validato

我有一个带有两个控件(port_start和port_end)的反应式表单,具有以下要求:

  • 两者都必须有一个值
  • 它们的值必须介于0和65535之间
  • 端口\u开始值必须小于端口\u结束值
这就是我迄今为止所尝试的:

[...]
this.formModel.addControl('port_start', 
  new FormControl(object.port_start ? object.port_start : 0, 
  [Validators.required, Validators.min(0), Validators.max(65535), this.minMaxValidator('port_start', 'port_end').bind(this)]));

this.formModel.addControl('port_end', 
  new FormControl(object.ort_end ? object.port_end : 0, 
  [Validators.required, Validators.min(0), Validators.max(65535), this.minMaxValidator('port_start', 'port_end').bind(this)]));
[...]
这是自定义验证器函数:

minMaxValidator = function(startControl : string, endControl : string): ValidatorFn {
  return (control: FormControl): {[key: string]: any} => {
    let valid = true;
    let valStart = 0;
    let valEnd = 0;

    if(this.formModel.controls[startControl] && this.formModel.controls[endControl]) {
      valStart = <number>this.formModel.controls[startControl].value;

      valEnd = <number>this.formModel.controls[endControl].value;
    }

    valid = valEnd >= valStart;

    return valid ? null : { minmax : true };
  };
}
minMaxValidator=函数(startControl:string,endControl:string):validator fn{
return(control:FormControl):{[key:string]:any}=>{
让valid=true;
设valStart=0;
设valEnd=0;
if(this.formModel.controls[startControl]&this.formModel.controls[endControl]){
valStart=this.formModel.controls[startControl].value;
valEnd=this.formModel.controls[endControl].value;
}
valid=valEnd>=valStart;
返回有效值?null:{minmax:true};
};
}
除此问题外,此操作正常:

  • 假设我在“端口开始”字段中键入“2”。Angular将其标记为无效,因为它大于“port_end”(默认为0)的值。如果我在“port_end”字段中键入“5”,应用程序仍会将“port_start”显示为无效,尽管现在它是正确的
我知道问题是,每次更改另一个字段的值时,我都需要重新检查关联字段,但我不知道如何做


有什么想法吗?谢谢,

所需的
min
max
验证器可以按原样保存。如果要基于另一个控件的值验证一个控件,则需要将验证提升到父控件

import { Component } from '@angular/core';
import { ValidatorFn, FormBuilder, FormGroup, Validators } from '@angular/forms';

const portStartEnd: ValidatorFn = (fg: FormGroup) => {
   const start = fg.get('portStart').value;
   const end = fg.get('portEnd').value;

   return start && end && start < end ? null : { startEnd: true };
}

@Component({
  selector: 'my-app',
  template: `
   <input [formControl]="form.get('portStart')" type="number" >
   <input [formControl]="form.get('portEnd')" type="number" >

   {{ form.valid }}
  `,
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  form: FormGroup;

  constructor(private fb: FormBuilder) {
    this.form = this.fb.group({
      portStart: [null, [Validators.required, Validators.min(0), Validators.max(65535)]],
      portEnd: [null, [Validators.required, Validators.min(0), Validators.max(65535)]]
    }, { validator: portStartEnd } );
  }
}
从'@angular/core'导入{Component};
从'@angular/forms'导入{ValidatorFn,FormBuilder,FormGroup,Validators};
const-portStartEnd:ValidatorFn=(fg:FormGroup)=>{
const start=fg.get('portStart').value;
const end=fg.get('portEnd').value;
返回start&&end&&start

与@Tomasz所说的不同,您可以将验证保持在控制级别

秘密:倾听表单上的更改,当更改发生时,用当前值设置验证程序

向您展示其工作原理

下面是我使用的代码:

从'@angular/core'导入{Component};
从“@angular/forms”导入{FormBuilder、FormGroup、ValidatorFn、AbstractControl};
@组成部分({
选择器:“我的应用程序”,
模板:`
最小值应小于最大值
最大值应小于最小值
`,
样式URL:['./app.component.css']
})
导出类AppComponent{
表格:表格组;
构造函数(私有fb:FormBuilder){
this.form=fb.group({
开始:[0],
完:[65535]
});
this.form.valueChanges.subscribe(changes=>{
this.form.get('start').setValidators(lessthanned(+this.form.value.end));
this.form.get('end').setValidators(超过start(+this.form.value.start));
});
}
}
导出函数lessthanned(结束:编号):validator fn{
return(control:AbstractControl):{[key:string]:any}=>{
return control.value>end?{'lessThan':true}:null;
};
}
导出函数多于开始(结束:编号):验证程序fn{
return(control:AbstractControl):{[key:string]:any}=>{
return control.value
Still+1用于解决方案,尽管可以将验证保持在控制级别。当然,您可以用另一种方法来进行验证,但我认为这更简单。毕竟这是一个交叉验证,那么为什么你要把这个验证保持在个人控制水平上呢?我完全同意。这就是为什么我没有说你应该,但只是说你可以。啊,好吧:)对创造性思维投赞成票^^不是真正的创造性,这是他要求的(改变听众)。假设OP在一个问题中学会了两种机制!(虽然我回答了您的问题,但这只是对更改侦听器的信息。如果您想实现一个有效的解决方案,请选择@Tomasz)感谢您的帮助,尽管两个答案都有效(我做了两个测试)我决定使用你的方法,因为它更容易适应我的代码。@我觉得这并不意味着它是最好的解决方案,甚至不是一个好的实践!这听起来可能有点奇怪,但是你能为将来和你有同样问题的用户将另一个答案标记为有效答案吗?没问题。我标记了你的答案,因为这是我在我的应用程序中使用的答案,但我可以选择另一个作为解决方案,因为我尝试了它,而且效果也很好。我遇到了一个与此相关的问题,因为我尝试在两个应用程序中使用此解决方案。问题在于,两个输入没有同时进行验证和更新,而是必须手动更改这两个值才能工作。你可以在stackblitz演示中看到我的意思;如果您通过单击增加或减少值的箭头来更改值(长时间单击。例如,要使开始超过结束,一旦您结束长时间单击,将只检查一个验证程序,而另一个错误仍然存在,即使不应该检查)。有没有办法解决这个问题?