我有一条指令:timelineItem
,该指令通过ng-repeat
重复。因此,应用程序中可能有1-100个(或更多)指令的实例。
所有这些时间轴项目元素都在其中嵌套了模板,我想等到ng-includes
完成加载然后再执行某些操作。因此,我在包含文件上放置了onload="vm.templateFinishedLoading()"
。
这就是被调用的函数:
public templatesFinishedLoading() {
this.i += 1;
if (this.i === this.activities.items.length) {
this.$rootScope.$broadcast('templatesFinishedLoading');
}
}
由于可以加载多个模板,所以我不想多次将$broadcast
放入for循环中。因此,当所有模板都加载完毕后,它将进行广播。
我想在模板加载完成后调用一个函数,以便将此$broadCast
捕获在timelineItem
指令中。由于伪指令的每个实例都捕获了$broadcast
,并且我只想对clicked元素进行动画处理,因此我必须将DOM中的被单击HTMLelement与伪指令的HTMLelement进行比较:
element.on('click', () => {
clickedElement = attr.$$element[0].parentElement;
}
然后在$broadcast
上,将clickedElement与attribute元素进行比较:
scope.$on('templatesFinishedLoading', () => {
if (attr.$$element[0].parentElement === clickedElement) {
console.log('true');
}
});
这始终等于true,因为我只更新了clicked指令上的clickedElement
变量。其他实例中的clickedElement
变量未更新,因为它们不在当前指令的范围内。
因此,我向点击添加了另一个$broadcast
:
element.on('click', () => {
$rootScope.$broadcast('resetClickedElement');
clickedElement = attr.$$element[0].parentElement;
}
然后在同一指令中,我接收广播:
scope.$on('resetClickedElement', () => {
clickedElement = document.createElement('div');
});
现在,当我单击具有指令的元素时:
<div class="activity-header" timeline-item>
我首先将重置广播到该指令的所有其他实例,以将clickedElement
更改为空的div元素。然后,将当前的clicked元素设置为clickedElement变量。因此,现在模板完成加载后,指令的所有实例都将执行if (attr.$$element[0].parentElement === clickedElement)
,只有单击的指令将具有正确的clickedElement
,因为所有其他指令均为空。
现在是我的问题。每个指令实例中是否还有另一种“重置” clickedElement
变量的方法?
答案 0 :(得分:0)
我对您的建议是您执行以下操作:
<div ng-app="app">
<div ng-repeat="item in [].constructor(10) track by $index">
<div timeline-item></div>
</div>
</div>
在您的应用程序中:
angular.module('app', [])
.controller('timelineController', TimelineController)
.directive('timelineItem', TimelineItem)
.factory('timelineService', TimelineService);
function TimelineController ($scope, $element, timelineService) {
timelineService.updateLoadedItems();
if (timelineService.isLoadFinished()) {
console.log('finished load the directives');
}
}
TimelineController.$inject = ['$scope', '$element', 'timelineService'];
function TimelineItem (timelineService) {
return {
template: '<div> timeline item {{selectedItem}}</div>',
link: function (scope, element, attrs) {
element.on('click', function () {
scope.$apply(function () {
timelineService.setClickedElement(element);
});
});
scope.$watch(function() {
return timelineService.getClickedElement();
}, function () {
scope.selectedItem = timelineService.getClickedElement() === element;
});
},
controller: TimelineController
}
}
TimelineItem.$inject = ['timelineService'];
function TimelineService () {
var loadedAllItems = false;
var clickedElement = null;
var itemsLength = 10;
var loadedItems = 0;
return {
getClickedElement: function () {
return clickedElement;
},
setClickedElement: function (element) {
clickedElement = element;
},
resetClickedElement: function () {
clickedElement = null;
},
isLoadFinished: function () {
return loadedAllItems;
},
updateLoadedItems: function () {
loadedItems++;
loadedAllItems = loadedItems == itemsLength;
}
}
}
这样做不需要广播,并且效果相同。