2013-12-17 12 views
6

を大事とき、私はちょうど角度からの奇妙な行動に遭遇しました:ここ角度ディレクティブの名前は本当に

シナリオです:

登録フォームでは、私は、HTTP呼び出して(電子メールの一意性をチェックしますサーバーへ)。
したがって、私はクライアントコードであるemailUniqueと呼ばれるディレクティブ作成:

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

ポストの残りのために、のは、ユーザーが入力していると仮定してみましょう:michaelを、それは明らかに有効なメールではありません。

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 
       }); 
      } 
     }; 
    }); 

一目見ただけで、答えを与える前に、応答は論理的に次のようになります:

に私は興味がある行動を誘発する、のは私の指示コードの面白い部分を見てみましょう

undefined 

なぜですか?なぜなら:

  • type="email"属性ではなく、単にtype="text"
  • michaelが有効なメールではありません私たちは、正確な。
  • Angularのコンパイラは、従来のHTMLの動作に準拠しているはずです。

これをテストした後、答えは期待通りにundefinedです。私の完全なディレクティブのロジックはそれに基づいており、全体がうまく動作します。

ここで、emailUniqueという名前をsomethingUniqueに変更しましょう。
クライアントが今いる:

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

サプライズ:console.log(viewValue)は今表示している:電子メールのフィールドを扱うときmichael、ないundefined ...

明らかに、名前を emailで始まる奇妙な効果がありますこの場合。

私の質問は簡単です:いい理由はありますか?バグはありますか?私はいくつかの考えを誤解するかもしれませんか?

いくつかの更なる精度:

  • 角度付きメール欄についてAngular's documentationemail-uniqueに干渉する可能性があり、いくつかのemail属性を提示していません。実際には、type="email"
  • に基づいています。フォームのnovalidate属性が存在するかどうかにかかわらず、同じ問題が発生しました。
+0

ここに私が問題を示すために作成したplunkrがあります:http://plnkr.co/edit/T9YfiDr5IU5vOrMtggY3?p=preview – Mik378

答えて

5

問題がディレクティブの優先順位です。パーサが追加されるタイミングに依存しているため、ディレクティブの優先順位を設定して、必要なタイミングを確保します。

あなたのデモでは、検証者がパーサーリストに追加される前に、somethingUniqueディレクティブが実行されています(3つのパーサーの途中で終了します)。一方、emailUniqueとの間に追加されます。

ディレクティブの優先順位を0以上に設定すると、undefinedというemailValidationの後に確実に発生します($compile docs:「ポストリンク関数は逆の順序で実行されます」を参照)。名前の問題について

.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

更新:あなたが何かにそれの優先順位を設定することにより、失敗するemailUniqueを強制することができ、これを確認するには0未満

は、これは問題を修正それをAngularプロセスのディレクティブはアルファベット順に同じ優先順位で表示されます。したがって、homethingUniqueemailUniqueのように動作します。両方ともinputの前に来るので、jomehtingUniquesomethingUniqueのように動作します。

しかし、Angular's docsは、「同じ優先度のディレクティブの順序は未定義です。」だから私たちはアルファベット順に数えられません。

+0

素晴らしいです。 "なぜ名前が重要かわかるのは、私がもっと掘り下げたいパズルだ" =>その理由を知ることは非常に興味がある。 – Mik378

+1

更新しました。 – KayakDave

+0

すばらしい、非常に興味深い:)しかし、1つの質問:ディレクティブの優先度が高いほど、パーザは早く実行されるでしょうか?私がsomethingUniqueに100を設定した場合、なぜそれが対応するパーサーがemailValidationより前に実行されないのですか?それは最初にプッシュされるからです。 - – Mik378

関連する問題