2013-12-17 14 views
6

Ho appena incontrato uno strano comportamento da Angular:Quando il nome di direttiva angolare è importante

Ecco lo scenario:

un modulo di registrazione, voglio verificare la presenza di unicità e-mail (attraverso un call http al server).
Così, ho creato una direttiva denominata emailUnique il cui codice cliente è:

<form name="form" novalidate> 
<!-- some other fields --> 
<input name="email" type="email" ng-model="user.email" required email-unique/> 
</form> 

Per il resto del post, supponiamo che l'utente sta scrivendo: michael, che non è chiaramente una mail valido.

Diamo uno sguardo alla parte interessante del mio codice direttiva, innescando il comportamento Sono interessato a:

angular.module('directives.emailUnique', []) 
    .directive('emailUnique', function() { 
     return { 
      restrict: 'A', 
      require: 'ngModel', 
      link: function (scope, el, attrs, ctrl) { 
       ctrl.$parsers.push(function (viewValue) { 
        console.log(viewValue); //What do you expect here for viewValue? answer below 
       }); 
      } 
     }; 
    }); 

Prima di dare la risposta, a prima vista, la risposta sarebbe logicamente:

undefined 

Perché? Perché:

  • Abbiamo precisa l'attributo type="email" e non semplicemente type="text"
  • michael non è una mail valido.
  • Il compilatore di Angular si suppone che sia conforme al classico comportamento HTML.

Dopo averlo provato, la risposta è undefined come previsto. La logica della mia direttiva completa sarà basata su questo e l'intero funziona bene.

Ora, rinominiamo la direttiva: emailUnique diventa somethingUnique.
Cliente essendo ora:

<input name="email" type="email" ng-model="user.email" required something-unique/> 

Sorpresa: il console.log(viewValue) è ora visualizzato: michael, non undefined ...

Chiaramente, a partire email per il nome ha un effetto strano quando si tratta di un campo di e-mail in questo caso.

La mia domanda è semplice: C'è una buona ragione? Un bug possibile? Potrei fraintendere qualche nozione?

Alcuni ulteriori precisazioni:

  • Il Angular's documentation merito campo Email con angolare non presenta alcuni email attributo che potrebbero interferire con email-unique. Infatti, è basato su type="email"
  • Mi sono imbattuto nello stesso problema se l'attributo novalidate del modulo è presente o meno.
+0

Ecco un plunkr che ho appena creato per mostrare il problema: http://plnkr.co/edit/T9YfiDr5IU5vOrMtggY3?p=preview – Mik378

risposta

5

Il problema è la priorità della direttiva. Dal momento che dipendi dal momento in cui vengono aggiunti i parser, devi impostare la priorità della direttiva, in modo tale da garantire i tempi necessari.

Nella tua demo la direttiva somethingUnique è in esecuzione prima che la convalida sia stata aggiunta all'elenco dei parser (finisce al centro di 3 parser). Considerando che con emailUnique è aggiunto dopo.

L'impostazione della priorità della direttiva su un valore superiore a 0 garantisce l'attivazione dopo l'emailValidazione che fornisce sempre undefined (dall'$compile docs: "le funzioni di post-collegamento vengono eseguite nell'ordine inverso"). A conferma di ciò si può forzare emailUnique a fallire impostandolo di priorità a qualcosa di meno di 0.

Quindi questo risolve il problema:

.directive('somethingUnique', function() { 
    return { 
     restrict: 'A', 
     require: 'ngModel', 
     priority: 100, 
     link: function (scope, el, attrs, ctrl) { 
      ctrl.$parsers.push(function (viewValue) { 
       console.log(viewValue); 
      }); 
     } 
    }; 
}); 

Updated plunker

Aggiornamento sulla questione del nome: E ' sembra che le direttive dei processi angolari abbiano la stessa priorità in ordine alfabetico. Quindi homethingUnique si comporta come emailUnique poiché entrambi vengono prima dello input mentre jomehtingUnique si comporta come somethingUnique - in esecuzione dopo l'input.

Ma Angular's docs dire: "L'ordine delle direttive con la stessa priorità non è definito." Quindi non possiamo contare sull'ordine alfabetico.

+0

Impressionante. "Perché il nome sembra importare qui è un enigma che voglio scavare in più" => molto curioso di conoscerne anche la ragione. – Mik378

+1

Capito, appena aggiornato. – KayakDave

+0

Grande, molto interessante :) Ma una domanda: più la 'priorità 'della direttiva è alta, più il suo parser sarà eseguito in anticipo, non è così? Se imposto 100 per qualcosa di Unico, perché il parser corrispondente non esegue PRIMA di e-mail validation, dal momento che sarebbe stato spinto il primo? supponendo che emailValidation abbia il valore predefinito 0. - – Mik378

Problemi correlati