我在动态创建表单时遇到问题。我有一个针对表单元素设置的指令。它使用 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">