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

Ben*_*ins 11 angular2-forms angular

我正在尝试为我的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
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我的形式未定义.

我该如何解决这个问题?

试试这个:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

但它会导致:

app/find-page/subcomponents/find-page/find-form.component.html:36:5导致错误:无法读取undefined的属性'value'

尝试这个:

class MealTypeValidator {

    constructor(private categoryFormControl: FormControl) { }

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

然后在我的表单组件中:

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,
    });
}
Run Code Online (Sandbox Code Playgroud)

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

Mic*_*ael 10

你离我更近了一步.

您需要将自定义验证器附加到其中FormGroup,因为它需要知道两个FormControl(categoriesmealTypes),因此附加到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
}
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,您实际上必须使用FormGroup构造函数而不是FormBuilder,因此您可以在参数中附加自定义验证.另外,将自定义验证器移到组件类之外.

看看这款Plunker,可以在这里更深入地了解您的具体案例.

  • 是否可以拥有多个表单组验证器?如果我想要除了依赖于多个控件的"validateMealType"之外的其他验证器,该怎么办? (2认同)

gin*_*alx 10

您可以通过该控件及其父表单组导航到另一个控件:

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

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

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

  • 这工作得很好,但在访问其他控件之前我必须检查父控件是否存在。另外 control.parent.get('anotherControl') 也会阻止 tslint 对你大喊大叫。 (2认同)

Mai*_*eck 5

@Michael 提出的解决方案对我来说很有效,但对 Angular 4 做了一些小改动。

\n\n

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

\n\n
function validateEqual(form: FormGroup): { [key: string]: boolean } {\n  const senha = form.controls['novaSenha'];\n  const confirmacaoSenha = form.controls['confirmacaoNovaSenha'];\n\n  if (senha != undefined && confirmacaoSenha != undefined) {\n    const senhaValue = senha.value;\n    const confirmacaoSenhaValue = confirmacaoSenha.value;\n\n    if (senhaValue !== confirmacaoSenhaValue) {\n        return { 'A senha e a confirma\xc3\xa7\xc3\xa3o n\xc3\xa3o coincidem.': true};\n    }\n\n    return null;\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

也谢谢@Ariel,他创建了这篇文章。

\n