Angular 2自定义验证器,它依赖于另一个表单控件

时间:2016-11-12 08:58:10

标签: angular angular2-forms

我试图为我的FormControl制作自定义验证器mealType

如果我的FormControl category有值且mealType没有,mealType应无效。

如果category没有值,则mealType应该有效。

我收到了控制台错误:

  

TypeError:无法读取属性' get'未定义的

代码:

ngOnInit() {
    this.findForm = this.formBuilder.group({
        categories: [null, Validators.required],
        mealTypes: [null, this.validateMealType],
        distanceNumber: null,
        distanceUnit: 'kilometers',
        keywords: null,
    });
}

validateMealType() {
    if (this.findForm.get('categories').value) {
        if (this.findForm.get('mealTypes').value) {
            var mealTypeError = false;
        } else {
            var mealTypeError = true;
        }
    } else {
        var mealTypeError = false;
    }

    return mealTypeError ? null : {
        error: true
    }
}

这是我的表格未定义。

如何解决此问题?

试试这个:

validateMealType(categoryControl: FormControl, mealTypeControl: FormControl) {
    if (categoryControl.value) {
        if (!mealTypeControl.value) {
            var mealTypeError = true;
        } else {
            var mealTypeError = false;
        }
    } else {
        var mealTypeError = false;
    }

    return mealTypeError ? null : {
        error: true
    }
}

但它会导致:

  

错误   应用程序/找到页/子/找到页/找到-form.component.html:36:5   造成:无法阅读财产'价值'未定义的

尝试这个:

class MealTypeValidator {

    constructor(private categoryFormControl: FormControl) { }

    mealTypeValidator(control: FormControl): { [error: string]: any } {
        if (this.categoryFormControl.value) {
            if (!control.value) {
                return { error: true };
            }
        }
    }
}

然后在我的表单组件中:

ngOnInit() {
    this.findForm = this.formBuilder.group({
        categories: [null, Validators.required],
        mealTypes: [null, new MealTypeValidator(this.findForm.get('categories').mealTypeValidator()],
        distanceNumber: null,
        distanceUnit: 'kilometers',
        keywords: null,
    });
}

但我有编译错误。我怎么做到这一点?我想我在我所做的验证课程和它的使用上都有点偏差。

4 个答案:

答案 0 :(得分:9)

你离我们更近了一步。

您需要将自定义验证器附加到FormGroup,因为它需要知道两个FormControlcategoriesmealTypes),因此附加到{{1将为验证者提供更广泛的视图并访问整个FormGroup

要实现这一目标,请将FormControl更改为

ngOnInit

在上面的代码中,您实际上必须使用ngOnInit() { this.findForm = new FormGroup({ mealTypes : new FormControl(null, Validators.Required), categories : new FormControl(null) // others form control here }, validateMealType); // <-- see here is your custom function } 构造函数而不是FormGroup,因此您可以在参数中附加自定义验证。另外,将自定义验证器移到组件类之外。

请查看此Plunker,以便在此处了解您的具体案例。

答案 1 :(得分:3)

@Michael提出的解决方案为Angular 4做了一些小改动。

在验证函数中,我需要将参数类型从AbstractControl更改为FormGroup,因为此版本中的AbstractControl不包含控件集合。

function validateEqual(form: FormGroup): { [key: string]: boolean } {
  const senha = form.controls['novaSenha'];
  const confirmacaoSenha = form.controls['confirmacaoNovaSenha'];

  if (senha != undefined && confirmacaoSenha != undefined) {
    const senhaValue = senha.value;
    const confirmacaoSenhaValue = confirmacaoSenha.value;

    if (senhaValue !== confirmacaoSenhaValue) {
        return { 'A senha e a confirmação não coincidem.': true};
    }

    return null;
  }
}

非常感谢@Ariel发现这篇文章。

答案 2 :(得分:0)

您可以在控件及其父窗体组中导航到另一个控件:

example(): ValidatorFn {
     return (control: AbstractControl): ValidationErrors | null => {
         const forbidden = control.value < control.parent.controls["anotherControl"].value;
         return forbidden ? { forbidden: { message: "Custom message" } } : null;
     };
}

将以上内容添加为组件内的函数,并将此验证器声明为表单控件:

formGroup = new FormGroup({
    //..
    targetControl: new FormControl("", [this.example()]),
    anotherControl: new FormControl("")
    //..
});

答案 3 :(得分:0)

mealTypes:[null,新的MealTypeValidator(this.findForm.get('categories')。mealTypeValidator()]

  • 您不能在builder子句中引用formGroup。

但是我们可以从控件中获取父对象,并使用可选的运算符可以引用值并获取另一个控件值,然后比较所需的逻辑。

ngOnInit() {
    this.findForm = this.formBuilder.group({
        categories: [null, Validators.required],
        mealTypes: [null, this.mealTypeValidator()],
        distanceNumber: null,
        distanceUnit: 'kilometers',
        keywords: null,
    });
}

mealTypeValidator(): ValidatorFn {
    return (control: AbstractControl): ValidationErrors | null => {
        return control.parent?.value.categories && !control.value
            ? { forbidden: { message: 'MealType should have a type under category!' } }
            : null;
    };
}