AngularJS: translating a single input element into a directive template without using a container

I would like to create a wrapper for my input field using the tooltip of the help-input tool inside it.

I use angular 1.0.7 if it is significant.

I use transclude: true, along with the selection area, to make mistakes in several different fields at the same time and still maintain a reference to the ng model on the outer $ area.

Problem :

when I use this directive in an input element, the input element does not clone ('Transclude') in the directive template.

As a result, I get an empty div element in the DOM with the ng-transclude attribute.

clink: http://plnkr.co/edit/vFB9ih6x2NBmwhAes3Qh?p=preview

code:

<input data-my-validate-input data-value-required="true" type="password" class="loginItem" placeholder="Password" name="password" data-ng-model="formData.password" data-display-name="Password"> 

However, when I wrap this input element in a span or div, the child input element is superior just fine, but then I do not get a link to the correct external ng model (ctrl) in the directive.

 <span data-my-validate-input data-value-required="true" data-display-name="Password"> <input type="password" class="loginItem" placeholder="Password" name="password" data-ng-model="formData.password" > </span> 

Full code (the logic inside the link function does not apply to the problem, but I preferred to publish the full code)

 directive('myValidateInput', function() { return { require: 'ngModel', restrict: 'A', transclude: true, scope: { displayName: '@', valueRequired: '@', maxLength: '@', minLength: '@', minLetters: '@', minNumbers: '@' }, template: '<div class="validationContainer">\ <div ng-transclude></div>\ <div class="input-help">\ <h4>{{fieldErrorDisplay}}</h4>\ <ul>\ <li data-ng-repeat="rule in requirementSpec" ng-class="rule.class">\ {{rule.msg}}\ </li>\ </ul>\ </div>\ </div>', replace: true, link: function(scope, elm, attrs, ctrl) { var validator = function(viewValue){ if(scope.valueRequired && viewValue.length == 0 && (!scope.maxLength && !scope.minLength && !scope.minLetters && !scope.minNumbers)){ scope.valid = false; scope.fieldErrorDisplay = scope.fieldName + ' is required'; } else{ scope.fieldErrorDisplay = scope.fieldName + ' must meet the following requirements: '; scope.requirementSpec = []; if(scope.minLength){ var itemValidity = viewValue.length >= scope.minLength; scope.valid = !itemValidity ? false : scope.valid; var item = { 'msg' : 'Must be at least ' + scope.minLength + ' characters long', 'class' : itemValidity ? 'valid' : undefined }; scope.requirementSpec[nameStr].push(item); } else if(scope.valueRequired){ var itemValidity = viewValue && viewValue.length >= 1; scope.valid = !itemValidity ? false : scope.valid; var item = { 'msg' : 'This field must be filled', 'class' : itemValidity ? 'valid' : undefined }; scope.requirementSpec[nameStr].push(item); } if(scope.maxLength){ var itemValidity = viewValue.length <= scope.maxLength; scope.valid = !itemValidity ? false : scope.valid; var item = { 'msg' : 'Must be ' + scope.maxLength + ' characters long at most ', 'class' : itemValidity ? 'valid' : undefined }; scope.requirementSpec[nameStr].push(item); } if(scope.minLetters){ var itemValidity = (viewValue && /[Az]/.test(viewValue)); scope.valid = !itemValidity ? false : scope.valid; var item = { 'msg' : 'Must contain at least ' + scope.minLetters + ' letters', 'class' : itemValidity ? 'valid' : undefined }; scope.requirementSpec[nameStr].push(item); } if(attrs.minNumbers){ var itemValidity = (viewValue && /\d/.test(viewValue)); scope.valid = !itemValidity ? false : scope.valid; var item = { 'msg' : 'Must contain at least' + attrs.minNumbers + ' numbers', 'class' : itemValidity ? 'valid' : undefined }; scope.requirementSpec[nameStr].push(item); } } if(scope.valid) { ctrl.$setValidity(nameStr, true); return viewValue; } else { ctrl.$setValidity(nameStr, false); return undefined; } } scope.requirementSpec = {}; ctrl.$parsers.unshift(function(viewValue) { return validator(viewValue); }); ctrl.$formatters.unshift(function(viewValue) { // var before = scope.$eval(attrs.validateBefore); if(viewValue && viewValue != "" && viewValue.length > 0) return validator(viewValue); }); }); } }); 
+6
source share
1 answer

Solution: $ transclude accepts only the compiled content of the element, not the element itself.

Obviously, I lack an understanding of this essential detail in my implementation.

+2
source

Source: https://habr.com/ru/post/955394/


All Articles