Aurelia 验证问题
Issue with Aurelia validation
我尝试动态添加验证,但验证方法 returns 仅出现第一个错误。
我的目标是使用来自服务器的所有验证规则解析 json 并动态添加验证。
我的html:
<input id="myInput1" value.bind="myInput1 & validateOnChangeOrBlur" errors.bind="myInput1Errors"/>
<input id="myInput2" value.bind="myInput2 & validateOnChangeOrBlur" errors.bind="myInput2Errors"/>
<button click.delegate='validate()'>validate</button>
<ul if.bind="controller.errors">
<li repeat.for="error of controller.errors">
${error.message}
</li>
</ul>
我的.ts:
attached() {
let rules = [];
//my real code is a for loop for adding dynamically
rules.push(ValidationRules
.ensure('myInput1')
.required()
.rules[0]);
rules.push(ValidationRules
.ensure('myInput2')
.required()
.rules[0]);
this.controller.addObject(this, rules);
}
validate() {
this.controller.validate()
.then(result => {
if (result.valid) {
//
} else {
//
}
});
}
当我模糊(选项卡导航)时,验证方法正确显示错误,一个接一个地堆叠它们。
当我调用验证时,它只显示第一个。
但是,如果我静态地执行此操作,它会起作用(模糊和验证):
ValidationRules
.ensure('myInput1')
.required()
.ensure('myInput2')
.required()
.on(this);
那么动态添加有什么问题呢?
我为此创建了一个 gistrun:https://gist.run/?id=c60ee8a86c9c473b97e930e117fd68df
谢谢。
通过动态创建它们的方式,您无意中创建了 sequenced 规则。由于您的问题,我还发现了一个非常微妙的错误。我将在下面解释。首先,有两种可能的解决方案:
解决方案 1
使 rules
成为数组的数组,并添加嵌套的数组项。
let rules = [[]];
//my real code is a for loop for adding dynamically
rules[0].push(ValidationRules
.ensure('myInput1')
.required()
.rules[0][0]);
rules[0].push(ValidationRules
.ensure('myInput2')
.required()
.rules[0][0]);
this.controller.addObject(this, rules);
解决方案 2
使用Rules.set
(这仍然是"wrong",我将在下面解释它为什么有效)
let rules = [];
//my real code is a for loop for adding dynamically
rules.push(ValidationRules
.ensure('myInput1')
.required()
.rules[0]);
rules.push(ValidationRules
.ensure('myInput2')
.required()
.rules[0]);
Rules.set(this, rules);
原因
外部数组是 规则序列 的数组(单独也是数组)。内部数组是该序列 .
中 规则的列表
通过将 .rules[0]
添加到数组,您最终得到一个规则序列数组,每个规则序列都有一个规则:
rules[0][0]
rules[1][0]
rules[2][0]
rules[3][0]
然而,当您将调用链接到同一个规则构建器时,它会在内部做正确的事情,.rules
将是一个包含所有单独规则的序列的数组:
rules[0][0]
rules[0][1]
rules[0][2]
rules[0][3]
序列
序列允许您按特定顺序执行规则,其中每个连续序列仅在所有先前序列评估为有效
时才被评估。因此,您创建的序列实际上按预期运行:第一个 属性 结果无效,其余未评估。
仅供参考,"normal" 创建顺序规则的方法是在规则生成器上使用 .then()
。只要您不使用 .then()
,您将始终拥有索引为 0
.
的 单个 序列
如何存储规则
当您使用 controller.addObject(this, rules)
时,规则存储在该控制器 上的地图 中。只有那个控制器会知道这些规则。
另一方面,Rules.set()
将规则存储在您提供的对象原型上的元数据对象 (属性 __rules__
) 中。终结器 .on()
以相同的方式存储它们(它只是调用 Rules.set()
)。这使得规则对所有控制器有效可用。
存储规则的处理方式有何不同
- 当您在控制器上调用
.validate()
时,它将首先查找通过 .addObject()
存储的 "local" 规则,然后通过 .validateObject()
将这些规则传递给验证器。
这就是你的情况。规则一次性处理,序列表现正常。
以下内容在技术上与您的问题无关,但我将其记录在此处以供参考。
- 然后它通过注册的绑定(由绑定行为添加)并且对于每个个体 属性 它会在验证器 上调用
.validateProperty()
如果对象没有被存储在控制器上.
所以这一步不会发生在你的情况下,但它会发生在我的 "solution 2" 上。序列不是在对象上 运行 一次,而是每个个体 运行 一次 属性,在某种程度上有效地绕过了序列的行为(它们仍然适用于 属性 级别, 只是不在对象级别)
所以我必须说这是一个有趣的发现:)
我尝试动态添加验证,但验证方法 returns 仅出现第一个错误。 我的目标是使用来自服务器的所有验证规则解析 json 并动态添加验证。
我的html:
<input id="myInput1" value.bind="myInput1 & validateOnChangeOrBlur" errors.bind="myInput1Errors"/>
<input id="myInput2" value.bind="myInput2 & validateOnChangeOrBlur" errors.bind="myInput2Errors"/>
<button click.delegate='validate()'>validate</button>
<ul if.bind="controller.errors">
<li repeat.for="error of controller.errors">
${error.message}
</li>
</ul>
我的.ts:
attached() {
let rules = [];
//my real code is a for loop for adding dynamically
rules.push(ValidationRules
.ensure('myInput1')
.required()
.rules[0]);
rules.push(ValidationRules
.ensure('myInput2')
.required()
.rules[0]);
this.controller.addObject(this, rules);
}
validate() {
this.controller.validate()
.then(result => {
if (result.valid) {
//
} else {
//
}
});
}
当我模糊(选项卡导航)时,验证方法正确显示错误,一个接一个地堆叠它们。 当我调用验证时,它只显示第一个。
但是,如果我静态地执行此操作,它会起作用(模糊和验证):
ValidationRules
.ensure('myInput1')
.required()
.ensure('myInput2')
.required()
.on(this);
那么动态添加有什么问题呢?
我为此创建了一个 gistrun:https://gist.run/?id=c60ee8a86c9c473b97e930e117fd68df
谢谢。
通过动态创建它们的方式,您无意中创建了 sequenced 规则。由于您的问题,我还发现了一个非常微妙的错误。我将在下面解释。首先,有两种可能的解决方案:
解决方案 1
使 rules
成为数组的数组,并添加嵌套的数组项。
let rules = [[]];
//my real code is a for loop for adding dynamically
rules[0].push(ValidationRules
.ensure('myInput1')
.required()
.rules[0][0]);
rules[0].push(ValidationRules
.ensure('myInput2')
.required()
.rules[0][0]);
this.controller.addObject(this, rules);
解决方案 2
使用Rules.set
(这仍然是"wrong",我将在下面解释它为什么有效)
let rules = [];
//my real code is a for loop for adding dynamically
rules.push(ValidationRules
.ensure('myInput1')
.required()
.rules[0]);
rules.push(ValidationRules
.ensure('myInput2')
.required()
.rules[0]);
Rules.set(this, rules);
原因
外部数组是 规则序列 的数组(单独也是数组)。内部数组是该序列 .
中 规则的列表通过将 .rules[0]
添加到数组,您最终得到一个规则序列数组,每个规则序列都有一个规则:
rules[0][0]
rules[1][0]
rules[2][0]
rules[3][0]
然而,当您将调用链接到同一个规则构建器时,它会在内部做正确的事情,.rules
将是一个包含所有单独规则的序列的数组:
rules[0][0]
rules[0][1]
rules[0][2]
rules[0][3]
序列
序列允许您按特定顺序执行规则,其中每个连续序列仅在所有先前序列评估为有效
时才被评估。因此,您创建的序列实际上按预期运行:第一个 属性 结果无效,其余未评估。仅供参考,"normal" 创建顺序规则的方法是在规则生成器上使用 .then()
。只要您不使用 .then()
,您将始终拥有索引为 0
.
如何存储规则
当您使用 controller.addObject(this, rules)
时,规则存储在该控制器 上的地图 中。只有那个控制器会知道这些规则。
另一方面,Rules.set()
将规则存储在您提供的对象原型上的元数据对象 (属性 __rules__
) 中。终结器 .on()
以相同的方式存储它们(它只是调用 Rules.set()
)。这使得规则对所有控制器有效可用。
存储规则的处理方式有何不同
- 当您在控制器上调用
.validate()
时,它将首先查找通过.addObject()
存储的 "local" 规则,然后通过.validateObject()
将这些规则传递给验证器。
这就是你的情况。规则一次性处理,序列表现正常。
以下内容在技术上与您的问题无关,但我将其记录在此处以供参考。
- 然后它通过注册的绑定(由绑定行为添加)并且对于每个个体 属性 它会在验证器 上调用
.validateProperty()
如果对象没有被存储在控制器上.
所以这一步不会发生在你的情况下,但它会发生在我的 "solution 2" 上。序列不是在对象上 运行 一次,而是每个个体 运行 一次 属性,在某种程度上有效地绕过了序列的行为(它们仍然适用于 属性 级别, 只是不在对象级别)
所以我必须说这是一个有趣的发现:)