0

我正在使用 AngularJS 来发现它的强大功能,但我不得不承认文档不是很发达,所以我在这里向社区询问我在嵌套指令方面面临的问题。

我更多的是寻找原因(以及我做错了什么的解释)而不是完成的解决方案。

所以事情就是这样(我正在使用角度消息,但我认为这并不重要,因为这个问题对于任何指令都是常见的):

为了快速更改错误管理,我决定将管理器(此处为 angular-messages)封装到指令中,因此要在表单上显示我的错误,我会这样做:

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