简体   繁体   English

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

[英]Updating Angular Controller with changes in Angular directive

 "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()}); } } } }); 
 <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> 

I have a controller which receives input from the user: next, previous, etc. based on the currentIndex. 我有一个控制器,它根据currentIndex接收来自用户的输入:下一个,上一个等。 I have a javascript timeline that runs in the directive that changes the currentIndex as it plays. 我有一个运行在指令中的javascript时间轴,该指令会在播放currentIndex时更改它。 At the end of each of the nested child timelines, updateCurrentIndex is fired. 在每个嵌套子时间轴的末尾,都会触发updateCurrentIndex。 It is necessary for me to communicate this change back to the controller so that the next, previous works on a meaningful currentIndex, not just what it was initialized in the beginning. 对于我来说,有必要将此更改传达回控制器,以便下一个先前的更改可以在有意义的currentIndex上工作,而不仅仅是在开始时初始化的内容。 The watch within my directive is registering the currentIndex = 0 initialization from my controller. 我指令中的监视正在从控制器中注册currentIndex = 0初始化。 So, I know that part of thecommunication works; 因此,我知道部分沟通工作; its from directive to controller that is the problem. 这是从指令到控制器的问题。

My directive has its scope set to true and restrict is 'E' , how do I get these currentIndex changes back to controller so currentIndex can be incremented and decremented appropriately based on the user input? 我的指令的作用域设置为true,restriction为'E',如何将这些currentIndex更改返回给控制器,以便可以根据用户输入适当地对currentIndex进行增减? I know my way around the chrome debugger fairly well but can't find currentIndex in the scope within my directive . 我非常了解chrome调试器,但是在指令的范围内找不到currentIndex。 Was thinking that using the correct relational scope to the controller along with apply would be the answer, but I am stuck. 我认为对控制器使用正确的关系范围以及应用将是答案,但是我被困住了。

Angular does not know when changes are made by GreenSock, so your scope hasn't been updated. Angular不知道GreenSock何时进行更改,因此您的范围尚未更新。 You can do this by using something like $scope.$apply() or $timeout() . 您可以使用$scope.$apply()$timeout()类的方法来执行此操作。 You might get digest errors using $apply, so I'd go with using $timeout in your onComplete callback. 使用$ apply可能会出现摘要错误,因此我会在onComplete回调中使用$ timeout。

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

Here's a demo that shows what happen when you don't use $apply or $timeout with a third-party library... nothing! 这是一个演示,演示了当您不将$ apply或$ timeout与第三方库一起使用时会发生什么……什么都没有! And yes, that includes jQuery too. 是的,它也包括jQuery。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM