使用Angular指令中的更改更新Angular Controller

时间:2016-03-24 19:52:38

标签: angularjs angularjs-directive greensock



"use strict";
angular.module("appBanner", [])
    .controller('bannerCtrl', function ($scope) {
		
		//...

        $scope.currentIndex = 0;
        $scope.setCurrentSlideIndex = function (index) {
            $scope.currentIndex = index;
        }

        $scope.isCurrentSlideIndex = function (index) {
            return $scope.currentIndex === index;
        };

        $scope.prevSlide = function () {
            $scope.currentIndex = ($scope.currentIndex < $scope.slides.length - 1) ? ++$scope.currentIndex : 0;
        };

        $scope.nextSlide = function () {
            $scope.currentIndex = ($scope.currentIndex > 0) ? --$scope.currentIndex : $scope.slides.length - 1;
        };
		
		//...

    })
    .directive('banner', function () {
		return {
			templateUrl: 'views/partials/banner.html',
			restrict: 'E',
			transclude: false,
			replace:true,
			scope: false,
			link: function postLink(scope, element, attrs) {
				
				//var imgSlides = ...
				//var progressBar = ...
				//var slideTime = ...
				
				var tlMaster = initMasterTimeline(imgSlides, progressBar, slideTime);
				
				function updateCurrentIndex(index) {
					scope.$apply(function() {
					  //***************************************************
					  /*    How do I communicate the new current index back to my controller from this directive?
					  /*
					  /*****************************************************/
				   });
				}
				
				function initMasterTimeline(imgSlides, progressBar, slideTime) {
					var tlAuto = initAutoTimeline(imgSlides, progressBar, slideTime);
					var tlBoatowners = initBoatownersTimeline(imgSlides, progressBar, slideTime);
					var tlCommercial = initCommercialTimeline(imgSlides, progressBar, slideTime);
								  
					var tlMaster = new TimelineMax({repeat:-1});
					tlMaster.set(progressBar, {scaleX:0, transformOrigin:"left"})
					.add(tlAuto, "auto")
					.add(tlBoatowners, "boatowners")
					.add(tlCommercial, "commercial");
									
					return tlMaster;
				}
				
				function initAutoTimeline(imgSlides, progressBar, slideTime) {
					var stayTime= 10; //for now, can make each timeline as long as you want later
								
					var tlAuto = new TimelineLite({
						onUpdate:setProgress, 
						onUpdateParams:["{self}", progressBar]
					});
								
					
					tlAuto.set(imgSlides[0], {display: "block"})
					.to(progressBar, slideTime, {autoAlpha: 1}, 0)
					.to(imgSlides[0], slideTime, {autoAlpha:1}, 0)
					.to(imgSlides[0], slideTime, {autoAlpha:0}, stayTime)
					.to(progressBar, slideTime, {autoAlpha:0}, stayTime)
					.set(imgSlides[0], {display: "none", onComplete: updateCurrentIndex(1)})
								
					return tlAuto;
				}
				
				function initBoatownersTimeline(imgSlides, progressBar, slideTime) {
					var stayTime= 10; //for now, can make each timeline as long as you want later
				
					var tlBoatowners = new TimelineLite({
						onUpdate:setProgress, 
						onUpdateParams:["{self}", progressBar]
					});
								
					
							
					tlBoatowners.set(imgSlides[1], {display: "block"})
					.to(progressBar, slideTime, {autoAlpha: 1}, 0)
					.to(imgSlides[1], slideTime, {autoAlpha:1}, 0)
					.to(imgSlides[1], slideTime, {autoAlpha:0}, stayTime)
					.to(progressBar, slideTime, {autoAlpha:0}, stayTime)
					.set(imgSlides[1], {display: "none", onComplete: updateCurrentIndex(2)});
						
					return tlBoatowners;	
				}
				
				function initCommercialTimeline(imgSlides, progressBar, slideTime) {
					var stayTime= 10; //for now, can make each timeline as long as you want later
								
					var tlCommercial = new TimelineLite({
						onUpdate:setProgress, 
						onUpdateParams:["{self}", progressBar]
					});
								
					
					tlCommercial.set(imgSlides[2], {display: "block"})
					.to(progressBar, slideTime, {autoAlpha: 1}, 0)
					.to(imgSlides[2], slideTime, {autoAlpha:1}, 0)
					.to(imgSlides[2], slideTime, {autoAlpha:0}, stayTime)
					.to(progressBar, slideTime, {autoAlpha:0}, stayTime)
					.set(imgSlides[2], {display: "none"}, onComplete: updateCurrentIndex(0));
					
					return tlCommercial;
				}
				
				function setProgress (timeline, progressBar){
					TweenMax.set(progressBar, {scaleX:timeline.progress()});
				}
			}
		}
	});
&#13;
<div ng-app="appBanner" ng-controller="bannerCtrl">
	<img class="imgSlide" src="images/slideshow/slideshow-1.jpg" >
	<img class="imgSlide" src="images/slideshow/slideshow-2.jpg" >
	<img class="imgSlide" src="images/slideshow/slideshow-3.jpg" >
	<div class="progress"></div>
	<div id="navArrowLeft" class="navArrow bannerNav" ng-click="prevSlide()">
		<div class="hidden-xs">
			<i class="fa fa-angle-double-left fa-5x"></i>
		</div>
		<div class="hidden-sm hidden-md hidden-lg">
			<i class="fa fa-angle-double-left fa-2x"></i>
		</div>
	</div>
	<div id="navArrowRight" class="navArrow bannerNav" ng-click="nextSlide()">
		<div class="hidden-xs">
			<i class="fa fa-angle-double-right fa-5x"></i>
		</div>
		<div class="hidden-sm hidden-md hidden-lg">
			<i class="fa fa-angle-double-right fa-2x"></i>
		</div>
	</div>
</div>
&#13;
&#13;
&#13;

  

我有一个控制器,它根据currentIndex接收来自用户的输入:next,previous等。我有一个javascript时间轴,在指令中运行,在播放时更改currentIndex。在每个嵌套的子时间轴的末尾,将触发updateCurrentIndex。我有必要将此更改传回控制器,以便下一个,之前的工作在有意义的currentIndex上,而不仅仅是在开始时初始化的内容。我的指令中的监视是从我的控制器注册currentIndex = 0初始化。所以,我知道部分通信工作;它从指令到控制器就是问题所在。

     

我的指令的范围设置为true,而限制是&#39; E&#39; ,如何将这些currentIndex更改返回到控制器,以便currentIndex可以根据用户输入适当增加和减少?我非常了解chrome调试器,但是在我的指令范围内找不到currentIndex。正在考虑使用正确的关系范围与控制器一起应用将是答案,但我被卡住了。

1 个答案:

答案 0 :(得分:1)

Angular不知道GreenSock何时进行更改,因此您的范围尚未更新。您可以使用$scope.$apply()$timeout()之类的内容来完成此操作。使用$ apply可能会出现摘要错误,所以我在你的onComplete回调中使用$ timeout。

function onComplete() {
  $timeout(function() {
    updateCurrentIndex(1);
  });
}

这是一个演示,显示当您不使用$ apply或$ timeout与第三方库时会发生什么......没有!是的,这也包括jQuery。

http://plnkr.co/edit/Z28hiklSk8IsyQ2Bi45s?p=preview