0

私はその力を発見するためにAngularJSをいじっていますが、ドキュメントがあまり開発されていないことを認めなければならないので、ネストされたディレクティブで直面している問題についてここでコミュニティに尋ねています.

私は、完成した解決策よりも、理由 (および私が間違っていることの説明) を探しています。

だからここにあります(私は角度メッセージを使用していますが、問題はどのディレクティブにも共通するので重要ではないと思います):

エラー管理をすばやく変更するために、マネージャー (ここでは角度メッセージ) をディレクティブにカプセル化することにしました。フォームにエラーを表示するには、次のようにします。

<script type="text/ng-template" id="default-error-messages">
  <error-message data-error="email" data-message="This field is not a valid email"></error-message>
  <error-message data-error="required" data-message="This field is required"></error-message>
  <error-message data-error="minlength" data-message="This field is too short"></error-message>
</script>
<form data-ng-submit="submitForm(registrationForm)" method="POST" name="registrationForm" novalidate>
    <input type="email" name="email" data-ng-model="user.email" required>
    <error-container data-watch-error-on="registrationForm.email.$error" data-default-errors="default-error-messages" data-ng-if="registrationForm.email.$dirty">
        <error-message data-error="required" data-message="test"></error-message>
    </error-container>
    <button type="submit" data-ng-disabled="registrationForm.$invalid">Register</button>
</form>


directives.directive('errorContainer', ['$compile',function($compile){
    return{
        restrict: 'E',
        transclude: true,
        replace: false,
        scope: {
            watchErrorOn: '@'
        },
        template: '<div class="error-container" data-ng-transclude></div>',
        compile: function(tElt, tAttrs, ctrl) {
            return {
                pre: function(scope, iElement, iAttrs){
                    iElement.find('.error-container').attr("data-ng-messages", scope.watchErrorOn);
                },
                post: function(scope, iElement, iAttrs){
                    if (angular.isDefined(iAttrs.defaultErrors)) {
                        var errorList = angular.element("<div data-ng-messages-include='" + (iAttrs.defaultErrors || 'default-error-messages') + "'></div>");
                        iElement.find('.error-container').append(errorList);
                        $compile(iElement)(scope);
                    }
                }
            }
        },
        link: function(scope, element, attrs, ctrl){
            $compile(element)(scope);
        }
    }
}]);


directives.directive('errorMessage', ['$compile', function($compile){
    return{
        restrict: 'E',
        template: '<div class="error"></div>',
        replace: true,
        scope:{
            message:'@',
            error:'@'
        },
        compile: function(tElt, tAttrs, ctrl){
            return{
                pre: function(scope, iElement, iAttrs){
                    iElement.attr('data-ng-message', scope.error);
                    iElement.text(scope.message);
                }
            }
        }
    }
}]);

ご承知のとおり、テンプレートにはデフォルトのエラーは一切含まれていません。プリ/ポスト コンパイル関数とリンクで多くの組み合わせを試しましたが、何も成功しませんでした。これはコンパイルの優先度の問題だと思います。おそらく ng-messages-include を最後にコンパイルする必要がありますが、その方法についてはわかりません。よろしくお願いします

4

2 に答える 2

0

ディレクティブ分離スコープ=の代わりに使用する必要があります。これは、分離スコープ直接変数に値を渡します。@data-watch-error-on="registrationForm.email.$error"watchErrorOn

scope: {
   watchErrorOn: '='
},

あなたが使用していたよう@に、補間ディレクティブで値を渡す必要がある一方向バインディング & を示しています{{}}が、重要なことはtrue&false値をディレクティブに渡したいということですが、補間された値でその値をディレクティブに渡した後、その値isolated scopeが変換されます&boolのような文字列にする必要はありません。を使用して値を渡すことは、ディレクティブ要素から渡すときに値を保持する双方向バインディングに他なりません。"false""true"=boolean

于 2015-09-05T18:20:29.213 に答える
0

さて、GitHub の投稿で方向性を示した後、解決策を見つけました。

この問題は、疑わしいように、AngularJS のコンパイル ポリシーによって引き起こされます。したがって、簡単に言うと、すべてのディレクティブをテンプレートに直接含めることが重要です。後でインクルードしても機能しますが、要素を手動でコンパイルする必要があります。

完全に奇妙なのは、プリコンパイル機能は、当然、コンパイル フェーズの前に「テンプレート文字列を変更する」ことと同じですが、明らかにそうではありません。

したがって、うまく機能する次のソリューションを検討してください。

html :

<form method="POST" name="registrationForm" novalidate>
    <input type="email" name="email" placeholder="Email address" data-ng-model="user.email" autocomplete="off" required>
    <button type="submit">Register</button>
<error-container data-messages-include="my-custom-messages" data-error-watch="registrationForm.email.$error">
    <error-message data-error="required" data-message="This field is required (version 1)"></error-message>
    <error-message data-error="email" data-message="This field must be an email"></error-message> 
</error-container>
</form>

ディレクティブ:

var app = angular.module('app', ['ngMessages']);
app.directive('errorContainer', function(){
    return{
        template: '<div ng-messages="watch"><div ng-messages-include="{{ messagesInclude }}"></div><div ng-transclude></div></div>',
        scope: {
          watch: '=errorWatch',                  
          messagesInclude: '@messagesInclude'                  
        },
        transclude: true
    };
});
app.directive('errorMessage', [function(){
    return{
        scope: {
          error: '@error',
          message: '@message'             
        },
        template: '<div ng-message="{{ error }}">{{ message }}</div>',
        replace: true
    }
}]);

最後に、AngularJS は間違いなく優れたフレームワークですが、私の観点からは、残念ながらいくつかの基本的なプロセスは十分に明確ではありません。

于 2015-09-10T13:14:47.717 に答える