我有两个指令,一个嵌套在彼此里面:
<envato class="container content-view-container" data-ng-cloak data-ng-hide="spinner">
<items data-ng-repeat="items in marketplaces"></items>
</envato>
这两者中的每一个都被定义为:
Application.Envato.directive("envato", ["$timeout", function($timeout){
var object = {
restrict : "E",
controller : "EnvatoAPIController",
transclude : true,
replace : true,
templateUrl : "templates/envato-view.php",
link : function(scope, element, attrs, controller) {
console.log(scope);
return controller.getLatestItems().then(function(data) {
scope.marketplaces = angular.fromJson(data);
scope.count = scope.marketplaces.length;
var tst = angular.element(element).find(".thumbnails");
/* $timeout(function() { scope.swiper = new Swipe(document.getElementById('swiper-container')); }, 5000); */
scope.spinner = false;
});
}
};
return object;
}]);
Application.Envato.directive("items", function(){
var iterator = [],
object = {
require : "^envato",
restrict : "E",
transclude : false,
replace : true,
templateUrl : "templates/envato-items-view.php",
link : function(scope, element, attrs, controller) {
iterator.push(element);
if (iterator.length === scope.$parent.$parent.count) { console.log(iterator); };
}
};
return object;
});
上面的许多代码可能没有多大意义,因为它是更大的应用程序的一部分,但我希望它能解决我的问题。我要做的是从指令envato
更改指令items
的范围属性。因为我有一个迭代,我想知道它何时完成,所以我可以在迭代期间对附加的DOM元素进行另一个操作。
例如,假设我将在指令scope.swipe
中定义envato
,并观察其变化。在指令items
中,我将关注ng-repeat
何时完成,然后更改上面定义的范围属性scope.swipe
。这将触发指令envato
内部的更改,现在我知道我可以执行操作。
我希望我足够清楚,如果不是我可以尝试更多代码,或者我会尝试更具体。我怎么能实现上面刚才描述的呢?
编辑:我知道在指令console.log(angular.element(element.parent()).scope());
中使用:items
会给我envato
指令的范围,但我想知道是否有更好的方法。
答案 0 :(得分:4)
对于这种指令间通信,我建议在envato
指令上定义一个API /方法,使您的items
指令可以调用。
var EnvatoAPIController = function($scope) {
...
this.doSomething = function() { ... }
}
您的items
指令已require
envato
指令,因此在items
指令的链接功能中,只需在适当的时候调用API:
require : "^envato",
link : function(scope, element, attrs, EnvatoCtrl) {
...
if(scope.$last) {
EnvatoCtrl.doSomething();
}
}
这种方法有什么好处,即使你有一天决定在你的指令中使用隔离范围,它也会有效。
AngularJS主页上的tabs
和pane
指令使用此通信机制。有关详细信息,请参阅https://stackoverflow.com/a/14168699/215945。另见约翰的Directive to Directive Communication video。
答案 1 :(得分:1)
在item
指令处使用scope.$eval('count')
,让角度为你解决。
答案 2 :(得分:1)
我认为您正在寻找在ng-repeat
完成时调用的回调。如果这就是你想要的,我创造了一个小提琴。 http://jsfiddle.net/wjFZR/
小提琴中没有多少UI。请打开firebug控制台,再次运行小提琴。你会看到一个日志。该日志在ng-repeat
指令中定义的cell
末尾调用。
$scope.rowDone = function(){
console.log($scope)
}
这是在row指令上定义的回调函数,当单元指令的ng-repeat
完成时将调用该函数。
以这种方式注册。
<cell ng-repeat="data in rowData" repeat-done="rowDone()"></cell>
免责声明:我也是angularjs的新手。
答案 3 :(得分:1)
嗯,看起来你正试图让自己变得困难。在您的指令中,您不设置范围属性:
var object = {
restrict : "E",
transclude : true,
replace : true,
scope: true,
...
设置范围:{}将为您的指令提供一个完全隔离的新范围。
但是设置范围:true将为您的指令提供一个完全隔离的新范围,该范围继承父级。
我使用此方法在顶级父指令中包含模型,并允许它过滤掉所有子指令。
答案 4 :(得分:0)
我喜欢Mark的答案,但我最终创建了一个属性指令,将元素指令的范围保存到rootScope,如下所示:
myApp.directive('gScope', function(){
return {
restrict: 'A',
replace: false,
transclude: false,
controller: "DirectiveCntl",
link: function(scope, element, attrs, controller) {
controller.saveScope(attrs.gScope);
}
}
});
...
function DirectiveCntl($scope, $rootScope) {
this.saveScope = function(id) {
if($rootScope.directiveScope == undefined) {
$rootScope.directiveScope = [];
}
$rootScope.directiveScope[id] = $scope;
};
}
...
<span>Now I can access the message here: {{directiveScope['myScopeId'].message}}</span>
<other-directive>
<other-directive g-scope="myScopeId" ng-model="message"></other-directive>
</other-directive>
注意:虽然这使得从所有各种指令收集数据变得轻而易举,但我谨慎地提醒您,现在您必须确保正确管理可能的作用域,以避免在页面上造成内存泄漏。特别是如果您使用ng-view创建单页应用程序。