【问题标题】:Issue with Aurelia validationAurelia 验证问题
【发布时间】:2018-09-14 02:38:24
【问题描述】:

我尝试动态添加验证,但 validate 方法只返回第一个错误。 我的目标是从服务器解析一个包含所有验证规则的 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 {
                       //
                    }
                });
        }

当我模糊(标签导航)时,验证方法会正确显示错误,并将它们一个接一个地堆叠起来。 当我调用 validate 时,它​​只显示第一个。

但是,如果我静态地执行此操作,它可以工作(模糊和验证):

ValidationRules
            .ensure('myInput1')
            .required()
            .ensure('myInput2')
            .required()
            .on(this);

那么动态添加有什么问题呢?

我为此创建了一个 gistrun:https://gist.run/?id=c60ee8a86c9c473b97e930e117fd68df

谢谢。

【问题讨论】:

标签: validation aurelia


【解决方案1】:

通过您动态创建它们的方式,您无意中创建了 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(这仍然是“错误的”,我将在下面解释为什么它仍然有效)

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]

序列

序列允许您按特定顺序执行规则,其中每个连续序列仅在所有先前序列评估为有效时评估。因此,您创建的序列实际上按预期运行:第一个属性被证明是无效的,其余的没有被评估。

仅供参考,创建有序规则的“正常”方式是在规则构建器上使用.then()。只要您不使用.then(),您将始终拥有一个索引为0单个序列。

规则是如何存储的

当您使用controller.addObject(this, rules) 时,规则存储在该控制器上的地图中。只有那个控制器会知道这些规则。

另一方面,Rules.set() 将规则存储在您提供给它的对象原型上的元数据对象(属性__rules__)中。终结器.on() 以相同的方式存储它们(它只是调用Rules.set())。这使得规则有效地可供所有控制器使用。

如何处理不同的存储规则

  1. 当您在控制器上调用.validate() 时,它会首先查找通过.addObject() 存储的“本地”规则,然后通过.validateObject() 将这些规则传递给验证器。

这就是您的情况。规则一次性处理完毕,序列按应有的方式运行。

以下内容在技术上与您的问题无关,但我在此处记录以供参考。

  1. 然后它会遍历已注册的绑定(由绑定行为添加),对于每个单独的属性,它会在验证器上调用.validateProperty()如果对象未存储在控制器上。。李>

所以这一步在你的情况下不会发生,但在我的“解决方案 2”中会发生。序列不是在对象上运行一次,而是每个属性运行一次,在某种程度上有效地绕过了序列的行为(它们仍然适用于属性级别,只是不适用于对象级别)

所以我必须说这是一个有趣的发现:)

【讨论】:

  • 解决方案 1 对我不起作用,我以迭代数组结束。 let keys = Object.keys(this.formData); keys.forEach(element =&gt; { this.controller.validate({object: this.formData[element], propertyName: 'value'}) .then(result =&gt; { if (result.valid) { console.log('valid'); } else { console.log('not valid'); } }); });
猜你喜欢
  • 2016-03-14
  • 2017-01-03
  • 1970-01-01
  • 2023-03-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多