在每个 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();
}
}
是的,这是可能的,但它需要稍微不同的方法。
这里有两点需要注意:
流畅的 api 初始化器(ValidationRules
上的静态方法 ensure()
)总是实例化一个 new FluentEnsure
对象。它不寻找现有的东西——即使你最终确定了同一个目标。要使用更多规则扩展规则集,您需要在现有规则集上调用 .ensure()
。
终结器(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 等藏在某个地方。
如果我有 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();
}
}
是的,这是可能的,但它需要稍微不同的方法。
这里有两点需要注意:
流畅的 api 初始化器(
ValidationRules
上的静态方法ensure()
)总是实例化一个 newFluentEnsure
对象。它不寻找现有的东西——即使你最终确定了同一个目标。要使用更多规则扩展规则集,您需要在现有规则集上调用.ensure()
。终结器(
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 等藏在某个地方。