在使用AngularJS制作错误消息指令时,我一直在努力解决范围问题。
我有一个ng-if和ng-class指令作为指令模板的一部分,但ng-class指令中的表达式似乎总是返回一个空字符串,除非:
查看我的指令的编译输出,如果删除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>
答案 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-if
。 replace
标记has got deprecation status,表示issues won't be fixed。当指令的模板获得额外的replace
包装器时(尽管它可能违反<div>
的目的),一切都应该按预期工作。
答案 1 :(得分:3)
通过使用replace=true
和ng-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;。