在每个 class 的基础上扩展 Aurelia 验证规则

Extend Aurelia Validation Rules on a per class basis

如果我有 class

export class Person {
    public name: string = "";
    public foo: string = "";
}

ValidationRules
    .ensure((p :Person) => p.name)
    .required()
    .withMessage("name is required")
    .on(Person);

有没有办法在每个控制器的基础上扩展这些规则?例如,在我的 App class 中,我还想确保 foo 属性 已设置,但是在此处将其添加为规则似乎会覆盖 name 规则来自上面的代码。

export class App {

    public person: Person = new Person();
    @observable
    public message: string = "";

    constructor(public vc: ValidationController, public vld: Validator) {

        ValidationRules
          .ensure((p: Person) => p.foo).required().withMessage("foo is required").on(this.person);


        this.vc.addObject(this.person);
        this.vc.validate();
    }
}

是的,这是可能的,但它需要稍微不同的方法。

这里有两点需要注意:

  1. 流畅的 api 初始化器(ValidationRules 上的静态方法 ensure())总是实例化一个 new FluentEnsure 对象。它不寻找现有的东西——即使你最终确定了同一个目标。要使用更多规则扩展规则集,您需要在现有规则集上调用 .ensure()

  2. 终结器(FluentEnsure 上的实例方法 on())将规则存储在 .prototype.__rules__(如果它是一个函数)或 .__rules__属性 将 覆盖 任何现有目标。

换句话说,当您最终确定 Person 的一个实例时,您正在 person.__rules__ 上存储一个全新的规则对象,它有效地 隐藏了 Person.prototype.__rules__.

郑重声明,静态方法 Rules.set(target, rules)Rules.get(target).__rules__ 属性 的包装器。您肯定会想调用这些而不是尝试直接访问 属性。

现在您可能会想到类似 Rules.get(Person).ensure(...).on(person) 的东西,但这也会修改 Person.prototype 上的原始规则。

那么如何处理呢?

输入标签

获取和组合规则集可能会变得混乱,但这是基本思想:

export class Person {}
ValidationRules.ensure(p => p.name).required().on(Person)

其他地方:

Rules.get(Person).ensure(p => p.foo).required().tag("foo");

其他地方:

Rules.get(Person).ensure(p => p.bar).required().tag("1234");

然后在验证的时候:

const allRules = Rules.get(Person); // "1234" is included
const fooRules = ValidationRules.untaggedRules(allRules)
         .concat(ValidationRules.taggedRules(allRules, "foo"); "1234" not included
vc.addObject(person);
vc.validate({ fooRules });

或者手卷什么的

我自己以前从未实际使用过标签,而且我见过一两个关于它们的问题。如果你想要更多,你也可以自己做类似的事情 control/transparency:

export class Person {
    public static scopedRules: { [scope: string]: any } = Object.create(null);
}
ValidationRules.ensure(p => p.name).required().on(Person)

其他地方:

Person.scopedRules.foo = Object.create(null);
ValidationRules.ensure(p => p.foo).required().on(Person.scopedRules.foo)

然后在验证的时候:

const rules = Rules.get(Person).concat(Rules.get(Person.scopedRules.foo));
vc.addObject(person);
vc.validate({ rules });

当然这只是一个"simplest possible thing"例子。在现实世界中,您可能会将规则 storage/retrieval/merging 等藏在某个地方。