0

我在动态创建表单时遇到问题。我有一个针对表单元素设置的指令。它使用 Jquery 通过 id 获取元素。然而,它似乎还没有被添加到 DOM 中。

            <form class="form-horizontal">
            <div class="control-group" ng-repeat="field in viewModel.fields">
                <label class="control-label">{{field.label}}</label>
                <div class="controls" ng-switch="field.type">
                    <input ng-switch-when="text" type="text" id="{{field.label}}" ng-model="field.data" validator="viewModel.validator"  ruleSetName="personFirstNameRules"/>
                    <span ng-switch-when="text" validation-Message-For="{{field.label}}"></span>
                </div>
            </div>

            <button ng-click="testID()">Submit</button>
        </form>

如果我对文本字段的 ID 属性和 span 元素验证-消息-For 进行硬编码,那么它们就没有问题。我未定义的区域是

    var errorElementController = angular.element(errorElement).controller('ngModel');
    var validatorsController = angular.element(errorElement).controller('validator');

完整的指令在这里

(function (angular, $) {

angular.module('directivesModule')
       .directive('validationMessageFor', [function () {
           return {
               link: function (scope, element, attributes) {
                   var errorElementId = attributes.validationMessageFor;
                   if (!errorElementId) {
                       return;
                   }
                   var areCustomErrorsWatched = false;

                   var watchRuleChange = function (validationInfo, rule) {
                        scope.$watch(function () {
                             return validationInfo.validator.ruleSetHasErrors(validationInfo.ruleSetName, rule.errorCode);
                        }, showErrorInfoIfNeeded);
                   };

                   var watchCustomErrors = function (validationInfo) {
                       if (!areCustomErrorsWatched && validationInfo && validationInfo.validator) {
                           areCustomErrorsWatched = true;
                           var validator = validationInfo.validator;
                           var rules = validator.validationRules[validationInfo.ruleSetName];
                           for (var i = 0; i < rules.length; i++) {
                               watchRuleChange(validationInfo, rules[i]);
                           }
                       }
                   };


                   //alert(errorElementId);

                   // get element for which we are showing error information by id
                   var errorElement = $("#" + errorElementId);

                   console.log(angular.element(errorElement));

                   var errorElementController = angular.element(errorElement).controller('ngModel');
                   var validatorsController = angular.element(errorElement).controller('validator');

                   console.log(errorElementController);
                   console.log(validatorsController);

                   var getValidationInfo = function () {
                       return validatorsController && validatorsController.validationInfoIsDefined() ? validatorsController.validationInfo : null;
                   };

                   var validationChanged = false;
                   var subscribeToValidationChanged = function () {
                       if (validatorsController.validationInfoIsDefined()) {
                           validatorsController.validationInfo.validator.watchValidationChanged(function () {
                               validationChanged = true;
                               showErrorInfoIfNeeded();
                           });

                           // setup a watch on rule errors if it's not already set
                           watchCustomErrors(validatorsController.validationInfo);
                       }
                   };

                   var getErrorMessage = function (value) {
                       var validationInfo = getValidationInfo();
                       if (!validationInfo) {
                           return '';
                       }

                       var errorMessage = "";
                       var errors = validationInfo.validator.errors[validationInfo.ruleSetName];
                       var rules = validationInfo.validator.validationRules[validationInfo.ruleSetName];

                       for (var errorCode in errors) {
                           if (errors[errorCode]) {
                               var errorCodeRule = _.findWhere(rules, { errorCode: errorCode });
                               if (errorCodeRule) {
                                   errorMessage += errorCodeRule.validate(value).errorMessage;
                                   break;
                               }
                           }
                       }

                       return errorMessage;
                   };

                   var showErrorInfoIfNeeded = function () {
                       var validationInfo = getValidationInfo();
                       if (!validationInfo) {
                           return;
                       }

                       var needsAttention = validatorsController.ruleSetHasErrors() && (errorElementController && errorElementController.$dirty || validationChanged);
                       if (needsAttention) {
                           // compose and show error message
                           var errorMessage = getErrorMessage(element.val());

                           // set and show error message
                           element.text(errorMessage);
                           element.show();
                       } else {
                           element.hide();
                       }
                   };

                   subscribeToValidationChanged();
                   if (errorElementController)
                   {
                     scope.$watch(function () { return errorElementController.$dirty; }, showErrorInfoIfNeeded);
                   }
                   scope.$watch(function () { return validatorsController.validationInfoIsDefined(); }, subscribeToValidationChanged());
               }
           };
       }]);})
   (angular, $);

控制台上的错误是

  TypeError: Cannot read property 'validationInfoIsDefined' of undefined
at subscribeToValidationChanged (http://localhost/trax/app/Directives/validationMessage.js:50:52)
at link (http://localhost/trax/app/Directives/validationMessage.js:103:24)
at nodeLinkFn (https://code.angularjs.org/1.2.13/angular.js:6271:13)
at compositeLinkFn (https://code.angularjs.org/1.2.13/angular.js:5682:15)
at publicLinkFn (https://code.angularjs.org/1.2.13/angular.js:5587:30)
at boundTranscludeFn (https://code.angularjs.org/1.2.13/angular.js:5701:21)
at Object.controllersBoundTransclude [as transclude] (https://code.angularjs.org/1.2.13/angular.js:6292:18)
at https://code.angularjs.org/1.2.13/angular.js:20073:32
at Array.forEach (native)
at forEach (https://code.angularjs.org/1.2.13/angular.js:304:11) <span ng-switch-when="text" validation-message-for="{{field.label}}" class="ng-scope"> 
4

1 回答 1

0

您在定义时将指令名称写为驼峰式大小写。在这种情况下,角度将此指令作为-基础值读取

所以validation-Message-For应该validation-message-for在你的 HTML 代码中

<span ng-switch-when="text" validation-message-for="{{field.label}}"></span>

并更改input id属性值分配类型:

删除{{}}fromid属性

<input ng-switch-when="text" type="text" id="field.label" ng-model="field.data" validator="viewModel.validator"  ruleSetName="personFirstNameRules"/>

更新

问题ng-switch when。在您的 Plunker 中,输入标签不会呈现为输入字段。

    Be aware that the attribute values to match against cannot be expressions. 
They are interpreted as literal string values to match against. For example,
 ng-switch-when="someVal" will match against the string "someVal" not against the 
value of the expression $scope.someVal.

参考这个问题。StackOverflow 问题

更新的 Plunker

于 2014-06-14T12:16:55.523 回答