重置指令中的值

时间:2018-07-25 12:11:12

标签: angularjs

我有一条指令: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变量的方法?

1 个答案:

答案 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;
    }
  }
}

这样做不需要广播,并且效果相同。