Angular 2条件Validators.required?

标签 angular typescript

我应该如何有条件地要求表单域?我制作了一个自定义验证器,但我传递给自定义验证器的条件变量是静态的,并保持其初始值。我的自定义验证器应该是什么样子才能获得更新的条件值?也许有一种方法可以使用 Validators.required 而不是自定义验证器来做到这一点?

private foo: boolean = false;
private bar: boolean = true;

constructor(private _fb: FormBuilder) {
    function conditionalRequired(...conditions: boolean[]) {
      return (control: Control): { [s: string]: boolean } => {
        let required: boolean = true;
        for (var i = 0; i < conditions.length; i++) {
          if (conditions[i] === false) {
            required = false;
          }
        }
        if (required && !control.value) {
          return { required: true }
        }
      }
    }
    this.applyForm = _fb.group({
          'firstName': ['', Validators.compose([
            conditionalRequired(this.foo, !this.bar)
          ])],
          ...
    });
}

更新(2016 年 5 月 17 日)

发布这篇文章已经有很长时间了,但我想引用 上可用的 .include().exclude() 方法ControlGroup 类,适用于尝试创建此功能的任何人。 ( docs ) 虽然可能有像上面这样的条件验证器的用例,但我发现包含和排除控件、控件组和控件数组是处理此问题的好方法。只需在您想要的控件上设置 required 验证器,然后根据需要包含/排除它。希望这对某人有帮助!

最佳答案

我想要一个更通用的版本,所以我为它编写了一个额外的验证器,可以与其他验证器组合在一起。我仍然刚刚开始研究表单模块,所以不要指望这是有史以来最有效的代码或在边缘情况下工作,但这是一个好的开始。它适用于正常用例,并且可以作为其他用例的良好起点。

为 rc.4 和新的表单模块制作,revalidateOnChanges 部分可能很糟糕(不确定导致此行为的最佳方法),使用风险自负! :)

如何使用它

验证器有两个参数,一个是给定 formGroup 的条件函数,如果要应用验证则预期返回 true,否则返回 false,以及一个验证器(可能是一个组合)。它会在 formGroup 更新时重新验证该字段,目前它只能检查同一 formGroup 内的内容,但这应该很容易修复。

this.formBuilder.group({
    vehicleType: ['', Validators.required],
    licencePlate: [
        '',
        ExtraValidators.conditional(
            group => group.controls.vehicleType.value === 'car',
            Validators.compose([
                Validators.required,
                Validators.minLength(6)
            ])
        ),
    ]
});

在此示例中,您有两个字段,vehicleType 和 licencePlate。如果 vehicleType 是“car”,条件语句将应用组合的验证器(必需和 minLength)。

您可以使用 compose 应用多个不同的条件,这些条件可能会或可能不会同时应用。这是一个稍微复杂一点的例子:

this.formBuilder.group({
    country: ['', Validators.required],
    vehicleType: ['', Validators.required],
    licencePlate: [
        '',
        Validators.compose([
            ExtraValidators.conditional(
                group => group.controls.vehicleType.value === 'car',
                Validators.required
            ),
            ExtraValidators.conditional(
                group => group.controls.country.value === 'sweden',
                Validators.minLength(6)
            ),
        ])
    ]
});

在这种情况下,如果 type 是“car”,我们应用 required,如果 country 是“Sweden”,我们应用 minLength。如果只有一个条件适用,则验证将适用,如果两个条件都适用,则两个验证都适用。

验证器本身

请注意,对象比较只是一个简单的蛮力,因为我们正在处理小对象,如果您使用 Ramda 或其他东西,您可以减少很多代码。

export class ExtraValidators {
    static conditional(conditional, validator) {
        return function(control) {
            revalidateOnChanges(control);

            if (control && control._parent) {
                if (conditional(control._parent)) {
                    return validator(control);
                }
            }
        };
    }
}
function revalidateOnChanges(control): void {
    if (control && control._parent && !control._revalidateOnChanges) {
        control._revalidateOnChanges = true;
        control._parent
            .valueChanges
            .distinctUntilChanged((a, b) => {
                // These will always be plain objects coming from the form, do a simple comparison
                if(a && !b || !a && b) {
                    return false;
                } else if (a && b && Object.keys(a).length !== Object.keys(b).length) {
                    return false;
                } else if (a && b) {
                    for (let i in a) {
                        if(a[i] !== b[i]) {
                            return false;
                        }
                    }
                }
                return true;
            })
            .subscribe(() => {
                control.updateValueAndValidity();
            });

        control.updateValueAndValidity();
    }
    return;
}

注意:记得导入运算符:
导入 'rxjs/add/operator/distinctUntilChanged';

关于Angular 2条件Validators.required?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36118721/

相关文章:

reactjs - TypeScript 和 createContext - 类型上缺少属性

javascript - 使用具有未定义启动值的管道

javascript - @syncfusion/ej2-ng-grids 中 GridComponent 的依赖关系解决

javascript - Angular 2 - Http Get 请求 - 传递 json 对象

angular - 如何使用@Input 将多个数据传递给子组件

javascript - 设置状态时这段代码是什么意思?

jquery - 转向 Typescript,数字错误

typescript - 如何使用 TypeScript 在 express 中输入 `request.query`?

typescript - Angular 2 typescript Unicode(阿拉伯语)文本支持

javascript - 自行销毁组件 - angular2