表单的自定义“多参数”验证器并不总是触发

时间:2016-04-07 23:36:58

标签: javascript typescript angular

我有一个Angular2.0.0-beta.9和Typescript 1.7应用程序。在这个应用程序中,我正在创建一个自定义验证器,它使用多个提供的参数来确定控件是否有效。

我使用this answer作为灵感

以下是我的表单类的构造函数:

constructor(fBuilder: FormBuilder) {

// initialize shift custom validators
this._sVal = new ShiftValidator; // a custom validator class I import

// build form controls
this.shiftForm = fBuilder.group({
    'TradeDate': ['2016-03-23', Validators.required],
    // other fields removed for brevity
    'SupervisorRankID': [0, (c: Control) => this._sVal.valSelectOptional(c, this.requireSupervisor())]
  });
}

这是验证器类:

export class ShiftValidator {

// other validations removed for brevity
valSelectOptional(c: Control, required: boolean): { [s: string]: boolean } {
    if (Number(c.value) < 1 && required) {
        return { 'invalidSelection': true };
    }
  }
}

这是我用来返回验证器第二个参数的布尔值的方法/函数:

    requireSupervisor(): boolean {
    if (this.currentTrade === undefined) { return false; }
    \\ NOTE: currentTrade is a custom class / object that is imported into this module
    if (this.currentTrade !== undefined) {
        return this.currentTrade.SupervisorApproval;
    } else {
        return false;
    }
}

问题

当我传递的booelan值更改为true时,此验证器仅“触发”。当我将requireSupervisor的值更改为false时,验证程序不会触发。

问题

有人可以帮我弄清楚为什么每次参数值改变时验证器都不会触发吗?

编辑1:

我通过在复选框中添加(ngModelChange)='requireSupervisor'并更改 requireSupervisor 功能以在整个控制组中包含updateValueAndValidate来尝试gunter的方法:

    requireSupervisor(): boolean {
    if (this.currentTrade === undefined) {
        this.validateSupervisor();
        return false;
    }

    if (this.currentTrade !== undefined) {
        this.validateSupervisor();
        return this.currentTrade.SupervisorApproval;
    } else {
        this.validateSupervisor();
        return false;
    }
}

validateSupervisor(): void {
    if (this.shiftForm !== undefined) {
        this.shiftForm.updateValueAndValidity();
    }
}

如果我将上面的validateSupervisor函数更改为以下内容,则会超出最大调用堆栈错误:

validateSupervisor(): void {
    if (this.shiftForm !== undefined) {
        this.shiftForm.controls['SupervisorRankID'].updateValueAndValidity();
    }
}

问题: 验证器逻辑工作,问题是验证器逻辑仅在单击/选中复选框时触发。取消选中/取消选中复选框后,不会触发验证程序。

有人可以帮我弄清楚为什么复选框的取消选中操作不会触发验证器吗?

4 个答案:

答案 0 :(得分:2)

似乎唯一的选择是:

control.updateValueAndValidity() 

虽然应小心添加其触发器以避免不期望的更改检测。

plunker

在此示例中,切换required工作正常,但如果您尝试直接从模板required!=required执行此操作,则会失败。

答案 1 :(得分:2)

AFAIK这是ControlGroup Validator的预期行为,仅针对更改的控件触发验证。

但是你可以按照Gunter和kemsky的建议使用updateValueAndValidity来操纵这种行为,只需要稍微微调一下

(<Control>this.shiftForm.controls['SupervisorRankID'])
   .updateValueAndValidity({onlySelf: true, emitEvent: true})

 // do this whenever requirement changes

注意:请勿将其放在requireSupervisor()validateSupervisor()内,因为这会导致递归。

  
      
  • 如果onlySelftrue,则此更改只会影响此Control的验证,而不影响其父组件的验证。
  •   
  • 如果emitEventtrue,则此更改将导致valueChanges上的Control事件被发出。
  •   
  • 这两个选项都默认为false
  •   

答案 2 :(得分:1)

这应该调用验证:

this.shiftForm.controls['SupervisorRankID'].updateValueAndValidity();

可能需要演员

(<Control>this.shiftForm.controls['SupervisorRankID'])
    .updateValueAndValidity();

答案 3 :(得分:0)

您可以尝试的一件事是将该formControl updateValueAndValidity方法的emitEvent设置为false。

例如类似

this.shiftForm.controls['SupervisorRankID'].updateValueAndValidity({emitEvent : false});
来自Angular docs的

  

如果emitEvent为true,则此更改将导致valueChanges事件   要发出的FormControl。默认为true(因为它下降   通过updateValueAndValidity)。

此外,您还可以将自己设为false(默认情况下为true),如下所示:

this.shiftForm.controls['SupervisorRankID'].updateValueAndValidity({onlySelf : true});

来自Angular docs:

  

如果onlySelf为true,则此更改只会影响验证   这个FormControl而不是它的父组件。默认为false。

我遇到了一个棘手而大的问题。 emitEvent救了我。

希望它对你有所帮助。

在此处详细了解formControl:https://angular.io/docs/ts/latest/api/forms/index/FormControl-class.html