当将函数传递给指令然后传递给嵌套的子指令时,在子指令的范围内检查时,始终将该函数视为已定义,无论它是否在父指令中传入。
有没有更好的方法来传递函数指针或检查它们是否在处理嵌套指令时被定义。
<body ng-app="myApp">
<div ng-controller="myController">
<dir1"></dir1>
</div>
<script type="text/ng-template" id="dir1">
<div>
<dir2 fun="fun()"></dir2>
</div>
</script>
<script type="text/ng-template" id="dir2">
<div>{{fun()}}</div>
<div>{{funDefined()}}</div> <!-- always true-->
</script>
</body>
var app = angular.module('myApp', []);
app.controller('myController', function($scope) {
$scope.fun = function() {
alert("function");
};
});
app.directive('dir1', function() {
return {
scope: {
fun: '&'
},
templateUrl: 'dir1'
};
});
app.directive('dir2', function() {
return {
scope: {
fun: '&'
},
link: function(scope, elem, attrs) {
scope.funDefined = function() {
return angular.isDefined(attrs.fun);
};
},
templateUrl: 'dir2'
};
});
答案 0 :(得分:0)
如果您在dir2的scope.funDefined
方法中设置调试器,则会看到attrs.fun
等于字符串"fun()"
。这是因为你从属性中获取原始值。由于它不是空字符串,它总是会给你true
。
此处已更新plunker
答案 1 :(得分:0)
我知道没有优雅的方式可以得到你想要的东西。就像之前提到的那样:
angular.isDefined(attrs.fun)
对字符串执行检查,因此每次定义fun
属性时它都将返回true。在您的dir1指令模板中,您有<dir2 fun="fun()"></dir2>
,因此显然定义了fun
(并且它是字符串)。如果你看看角度来源:
case '&':
// Don't assign Object.prototype method to scope
parentGet = attrs.hasOwnProperty(attrName) ? $parse(attrs[attrName]) : noop;
// Don't assign noop to destination if expression is not valid
if (parentGet === noop && optional) break;
destination[scopeName] = function(locals) {
return parentGet(scope, locals);
};
break;
你会看到属性的存在总是会导致一些函数分配给范围($parse
返回函数,即使对于没有多大意义的字符串也是如此。)
因此,我能想到的唯一解决方案是执行第一级指令检查(因为属性确实未定义),并且有两个<dir2>
标签(有和没有fun
属性) - 始终使用ng-if
排除一个。像this这样的东西。我知道,这是一个丑陋的解决方案。
一方面注意 - Angular的源代码还显示,如果没有属性且绑定是可选的(使用&?
),则不会设置scope属性 - 然后您可以检查scope.fun
值而不是{{1有些人可能会觉得它更优雅。
答案 2 :(得分:0)
我能找到的最佳方式是基于@xersiee在另一个答案中所评论的内容。我们的想法是在父指令中使scope参数可选,然后使用angular.isUndefined(scope.$parent.$eval(attribute.myFun))
来检查函数是否被传递。这在官方文档中没有解释......我想知道为什么。
正如其他人所提到的,这个解决方案远非理想,因为使用范围。$ parent是一种反模式,但同样,这是我能找到的最佳选择。
使用此解决方案的Plunker:http://plnkr.co/edit/SUUMae?p=preview