隔离范围问题和"替换:true"在角度指令

时间:2016-03-27 10:03:18

标签: angularjs angularjs-directive

在使用AngularJS制作错误消息指令时,我一直在努力解决范围问题。

我有一个ng-if和ng-class指令作为指令模板的一部分,但ng-class指令中的表达式似乎总是返回一个空字符串,除非:

  1. 我删除了ng-if指令。
  2. 或者,我删除了'替换'指令定义对象中的键。
  3. 查看我的指令的编译输出,如果删除ng-if或replace键,看起来像是创建了一个隔离的范围,但是如果它们都被保留,那么就没有ng-isolate-scope html输出中的类,只是ng-scope。

    我真的很想明白这里到底发生了什么,并且会对任何解释感激不尽。

    指令定义

    angular.module('myMessages')
    .directive('pageMessages', function() {
    
        return {
            restrict: 'E',
            replace: true,
            scope: {
                messages: '='
            },
            controller: function($scope) {
                $scope.severity = 'alert-success';
            },
            template: '<div ng-if="messages.length > 0">' +
                        '<div class="alert" ng-class="severity">' + 
                            '<ul>' + 
                                '<li ng-repeat="m in messages">{{::m.message}}</li>' +
                            '</ul>' +
                        '</div>' +
                      '</div>'
        };
    });
    

    输出(注意没有添加警报危险类别)

    <!-- ngIf: messages.length > 0 -->
    <div ng-if="messages.length > 0" messages="messages" class="ng-scope">
        <div class="alert" ng-class="severity">
            <ul>
            <!-- ngRepeat: m in messages -->
                <li ng-repeat="m in messages" class="ng-binding ng-scope">test error</li>
            <!-- end ngRepeat: m in messages --></ul>
        </div>
    </div>
    <!-- end ngIf: messages.length > 0 --></div>
    

    在删除替换后添加alert-danger类(删除ng-if也可以)

    <page-messages messages="messages" class="ng-isolate-scope">
        <!-- ngIf: messages.length > 0 -->
        <div ng-if="messages.length > 0" class="ng-scope">
            <div class="alert alert-danger" ng-class="severity">
                <ul>
                <!-- ngRepeat: m in messages -->
                    <li ng-repeat="m in messages" class="ng-binding ng-scope">test error</li>
                <!-- end ngRepeat: m in messages -->
                </ul>
            </div>
        </div>
        <!-- end ngIf: messages.length > 0 -->
    </page-messages>
    

2 个答案:

答案 0 :(得分:4)

truthy df["EmployeeName"].concatenate(df2011["JobTitle"]) 的工作是克隆原始元素并赋予其继承范围。它为此使用了转换,这允许ng-if在具有隔离范围的元素上获取继承范围,避免ng-if判决出现$compile:multidir错误。

好处是,如果在具有隔离范围的元素上使用它,它将不会抛出错误。不好的是,当用于具有更高优先级的指令(Multiple directives requesting new/isolated scope优先级为600)时,它只会替换它,忽略其范围。另一个坏处是,当在带有隔离范围的指令的根模板元素上使用时(就像这一个),它只会用克隆的元素替换一个从父范围继承其范围的元素(属于指令的父元素,因为它自己的元素已被ng-if)替换。

因此它只从replace父范围获取severity值,并将pageMessages表达式计算为空字符串(如果它不存在)。

解决方案是不要在带有ng-class标志的指令的根元素上使用ng-ifreplace标记has got deprecation status,表示issues won't be fixed。当指令的模板获得额外的replace包装器时(尽管它可能违反<div>的目的),一切都应该按预期工作。

答案 1 :(得分:3)

通过使用replace=trueng-if并将范围隔离在一起,代码尝试在同一元素上使用不同范围的指令。

来自文档:

  

通常,可以将多个指令应用于一个元素,但可能存在一些限制,具体取决于指令所需的范围类型。以下几点有助于解释这些限制。为简单起见,只考虑了两个指令,但它也适用于几个指令:

     
      
  • 没有范围+没有范围=&gt;两条不需要自己范围的指令将使用其父母的范围
  •   
  • 子范围+无范围=&gt;这两个指令将共享一个子子范围
  •   
  • 子范围+子范围=&gt;这两个指令将共享一个子子范围
  •   
  • 隔离范围+无范围=&gt; Isolated指令将使用它自己创建的隔离范围。另一个指令将使用其父级的范围   孤立范围+儿童范围=&gt;不上班!只有一个范围可以与一个元素相关。因此,这些指令不能应用于同一元素。
  •   
  • 隔离范围+隔离范围=&gt;不上班!只有一个范围可以与一个元素相关。因此,这些指令不能应用于同一元素。
  •   

- AngularJS Comprehensive Directive API - scope

replace:true已弃用 1

来自文档:

  

replace([已弃用!],将在下一个主要版本中删除 - 即v2.0)

     

指定模板应替换的内容。默认为false

     
      
  • true - 模板将替换指令的元素。
  •   
  • false - 模板将替换指令元素的内容。
  •   

- AngularJS Comprehensive Directive API

来自GitHub:

  

Caitp--它被弃用了,因为replace: true存在已知的非常愚蠢的问题,其中一些问题无法以合理的方式得到解决。如果你小心并避免这些问题,那么对你有更多的权力,但为了新用户的利益,告诉他们更容易,这会让你头疼,不要这样做&#34;。

- AngularJS Issue #7636