代码之家  ›  专栏  ›  技术社区  ›  Mac

Angular ngMessages-访问多个表单值

  •  0
  • Mac  · 技术社区  · 9 年前

    我正在尝试向Angular的ngMessages添加一个自定义验证函数。

    具体来说,我希望一些输入的值(输入的数量是动态的,但目前坚持2)总计为100。

    totalOneHundred 它会在表单更改时触发,但我不知道如何从 link: 回电

    我已经在下面发布了我的代码。我有什么遗漏吗?此外,如果有更好的方法来实现这一点(a sum() 控制器和 ng-show 例如)请叫我出来。

    表格:

    <!-- input box to be validated -->
    <input type="number" class="form-control" name="lowBound" ng-model="ctrl.lowBound" total-one-hundred required>
    
    <!-- validation messages -->
    <div ng-messages="form['lowBound'].$error" role="alert">
        <div ng-message="required">Cannot be empty</div>
        <div ng-message="totalOneHundred">Sum of tasks must = 100</div>
    </div>
    
    <!-- input box to be validated -->
    <input type="number" class="form-control" name="highBound" ng-model="ctrl.highBound" total-one-hundred required>
    
    <!-- validation messages -->
    <div ng-messages="form['highBound'].$error" role="alert">
        <div ng-message="required">Cannot be empty</div>
        <div ng-message="totalOneHundred">Sum of tasks must = 100</div>
    </div>
    

    指令:

    return {
        restrict: "A",
    
        require: ["^^form", "ngModel"],
    
        link: function(scope, element, attributes, controllers) {
    
            // At first, form is assigned the actual form controller...
            const form = controllers[0];
            const model = controllers[1];
    
            model.$validators.totalOneHundred = function (modelValue, form, element, scope) {
    
              // however, the value of form here is "1".
              // modelValue is the value of the triggering input, 
              // but how can I access the other form inputs?
              return true;
    
            };
    
        }
    };
    
    1 回复  |  直到 9 年前
        1
  •  1
  •   Graham francescalus    8 年前

    最初我采用了您的代码并实现了 this fiddle A. sum() 父控制器的方法计算总数(很简单,但因为父控制器知道整个动态模型,所以在实际情况下也是可行的)。这个 total-one-hundred 以总和作为参数,即:

    <input type="number" class="form-control" name="lowBound" ng-model="ctrl.lowBound"
        total-one-hundred="ctrl.sum()" required />
    

    唉, 它不能正常工作 ! 问题:每个输入都显示“任务总数必须=100”错误。如果您更改了一个字段,并且总计正确,则该字段将有效并停止显示消息。但其他领域没有!


    编辑: 好吧,它 可以 即使是这样。秘诀是在每个验证指令的总和上添加一个监视,并在该字段上重新应用验证;新链接功能:

      link: function(scope, element, attributes, controllers) {
          const model = controllers[0];
          var totalEvaluator = $parse(attributes['totalOneHundred']);
    
          scope.$watch(totalEvaluator, function(newval, oldval) {
            if( newval !== oldval ) {
                model.$validate();
            }
          })
    
          model.$validators.totalOneHundred = function (modelValue) {
            return totalEvaluator(scope) === 100;
          };
      }
    

    (请注意,这需要每个场额外的手表!)

    sum() 函数(可能很昂贵)被多次调用。观察此函数的输入并仅在其更改时调用它,可以改善情况。

    更新版小提琴: https://jsfiddle.net/m8ae0jea/1/ (我仍然喜欢模型验证——见最后一段——但最好了解所有替代方案及其副作用。)


    this fiddle .

    现在模型看起来像:

    this.model = {
        lowBound: <a number>,
        highBound: <a number>
    };
    

    还有一个用于整个模型的编辑器,包括它自己的消息:

    <model-editor name="entireModel" ng-model="ctrl.model" form="form"
        total-one-hundred="ctrl.sum()"></model-editor>
    <div ng-messages="form['entireModel'].$error" role="alert">
      <div ng-message="totalOneHundred">Sum of tasks must = 100</div>
    </div>
    

    如您所见,整个验证适用于整个模型。

    如果整个“总体”验证只需要一条消息,那么第二个示例可以正常工作。但我不喜欢。。。

    Angular的验证是(IMHO)一种快速而肮脏的解决方案,适用于简单的事情。比如说,一个字段不能为空,另一个字段必须符合正则表达式等。对于复杂的事情(比如这种情况),我发现在视图中定义业务逻辑是不合适的。我更喜欢做模型验证,并将验证结果与Angular绑定。在这种程度上,我创造了 egkyron