6

Vorrei creare un wrapper per il mio campo di input con un suggerimento di input-help all'interno di esso.AngularJS: Trascludi un singolo elemento di input in un modello di direttiva senza utilizzare un contenitore

Sto usando angular 1.0.7, se è significativo.

Sto utilizzando transclude: true, insieme all'ambito isolato per consentire errori in diversi campi contemporaneamente e mantenere il riferimento del modello ng all'ambito $ esterno.

Il problema:

quando uso questa direttiva sul l'elemento di input, l'elemento di input non clone ('Transclude') nel modello direttiva.

Come risultato, ottengo un elemento div vuoto nel DOM, con un attributo ng-transclude.

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

codice:

<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"> 

Tuttavia quando ho avvolgere questo elemento di input in un arco o di div, l'elemento di input bambino è trasceso bene, ma poi non ho ricevuto il riferimento al modello ng esterno corretto (ctrl) alla direttiva.

<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> 

codice completo (la logica all'interno della funzione di collegamento non è rilevante per il problema, ma ho preferito postare il mio codice completo)

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 && /[A-z]/.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); 

      }); 


     }); 
    } 
}); 
+0

puoi pubblicare il modello HTML che hai usato, sarà bello vedere il tuo problema in Fiddle/Plunker. Grazie –

+0

Plunk aggiunto: http://plnkr.co/edit/vFB9ih6x2NBmwhAes3Qh?p=preview –

risposta

2

La soluzione: $ transclude prende solo il contenuto compilato dell'elemento, quindi non l'elemento stesso.

Ovviamente mi manca la comprensione di questo dettaglio significativo nella mia implementazione.

Problemi correlati