I am having a problem with the dynamic creation of a Form. I have a directive that gets set against a form element. It uses Jquery to get the element by id. However it seems that it has not yet been added to the 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>
If I hard code the ID attribute for the text field and on the span element validation-Message-For then their is no issue.The area where i am getting undefined is
var errorElementController = angular.element(errorElement).controller('ngModel');
var validatorsController = angular.element(errorElement).controller('validator');
The full directive is here
(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, $);
The error on the console is
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">