How do you Bind to Angular-UI's Carousel Slide Events?

后端 未结 6 1655
一整个雨季
一整个雨季 2020-12-02 21:24

I\'m using Angular-UI\'s carousel and I need to tell my google charts to redraw after they have slid into view. In spite of what I\'ve read, I can\'t seem to hook into the e

相关标签:
6条回答
  • 2020-12-02 22:00

    Following the answer given by runTarm If you want to know the index of the next slide, you should add something like this:

     .directive('onCarouselChange', function ($parse) {
        return {
          require: 'carousel',
              link: function (scope, element, attrs, carouselCtrl) {
                var fn = $parse(attrs.onCarouselChange);
                var origSelect = carouselCtrl.select;
                carouselCtrl.select = function (nextSlide, direction,nextIndex) {
          if (nextSlide !== this.currentSlide) {
            fn(scope, {
              nextSlide: nextSlide,
              direction: direction,
              nextIndex:this.indexOfSlide(nextSlide)
            });
          }
          return origSelect.apply(this, arguments);
        };
      }
      };
    })
    

    Then, in the controller you just need to do this to catch the new index:

    $scope.onSlideChanged = function (nextSlide, direction, nextIndex) {
        console.log(nextIndex);
    }
    
    0 讨论(0)
  • 2020-12-02 22:02

    here's an alternate method that uses controllers, somewhere between runTarm's #2 and #3.

    original HTML + a new div:

    <carousel id="myC" interval="myInterval">
      <slide ng-repeat="slide in slides" active="slide.active">
        <div ng-controller="SlideController"> <!-- NEW DIV -->
          <img ng-src="{{slide.image}}" style="margin:auto;">
          <div class="carousel-caption">
            <h4>Slide {{$index}}</h4>
            <p>{{slide.text}}</p>
          </div>
        </div>
      </slide>
    </carousel>
    

    the custom controller:

      .controller('SlideController',
        function($log, $scope) {
          var slide = $scope.slide;
          $scope.$watch('slide.active', function(newValue) {
            if (newValue) {
              $log.info("ACTIVE", slide.id);
            }
          });
        });
    
    0 讨论(0)
  • 2020-12-02 22:15

    I managed to modify runTarm's answer so that it calls the callback once the slide has finished sliding into view (i.e. the sliding animation has finished). Here's my code:

    .directive('onCarouselChange', function ($animate, $parse) {
        return {
            require: 'carousel',
            link: function (scope, element, attrs, carouselCtrl) {
                var fn = $parse(attrs.onCarouselChange);
                var origSelect = carouselCtrl.select;
                carouselCtrl.select = function (nextSlide, direction) {
                    if (nextSlide !== this.currentSlide) {
                        $animate.on('addClass', nextSlide.$element, function (elem, phase) {
                            if (phase === 'close') {
                                fn(scope, {
                                    nextSlide: nextSlide,
                                    direction: direction,
                                });
                                $animate.off('addClass', elem);
                            }
                        });
                    }
                    return origSelect.apply(this, arguments);
                };
            }
        };
    });
    

    The secret lies in using $animate's event handler to call our function once the animation is finished.

    0 讨论(0)
  • 2020-12-02 22:17

    And if you just want to start playing a video when the slide comes into view, and pause when it leaves:

    JS

    {# Uses angular v1.3.20 & angular-ui-bootstrap v0.13.4 Carousel #}
    {% addtoblock "js" %}<script type="text/javascript">
    angular.module('videoplay', []).directive('videoAutoCtrl', function() {
      return {
        require: '^carousel',
        link: function(scope, element, attrs) {
          var video = element[0];
          function setstate(visible) {
            if(visible) {
              video.play();
            } else {
              video.pause();
            }
          }
          // Because $watch calls $parse on the 1st arg, the property doesn't need to exist on first load
          scope.$parent.$watch('active', setstate);
        }
      };
    });
    </script>{% endaddtoblock %}
    {% addtoblock "ng-requires" %}videoplay{% endaddtoblock %}
    

    NOTE: Has additional bits for Django

    HTML:

    <carousel interval="15000">
      <slide>
       <video class="img-responsive-upscale" video-auto-ctrl loop preload="metadata">
        <source src=
    ...
    
    0 讨论(0)
  • 2020-12-02 22:20

    There are 3 ways I can think of and that depends of your requirement.

    Please see http://plnkr.co/edit/FnI8ZX4UQYS9mDUlrf6o?p=preview for examples.

    1. use $scope.$watch for an individual slide to check if it is become active.

      $scope.$watch('slides[0].active', function (active) {
        if (active) {
          console.log('slide 0 is active');
        }
      });
      
    2. use $scope.$watch with custom function to find an active slide.

      $scope.$watch(function () {
        for (var i = 0; i < slides.length; i++) {
          if (slides[i].active) {
            return slides[i];
          }
        }
      }, function (currentSlide, previousSlide) {
        if (currentSlide !== previousSlide) {
          console.log('currentSlide:', currentSlide);
        }
      });
      
    3. use a custom directive to intercept select() function of the carousel directive.

      .directive('onCarouselChange', function ($parse) {
        return {
          require: 'carousel',
          link: function (scope, element, attrs, carouselCtrl) {
            var fn = $parse(attrs.onCarouselChange);
            var origSelect = carouselCtrl.select;
            carouselCtrl.select = function (nextSlide, direction) {
              if (nextSlide !== this.currentSlide) {
                fn(scope, {
                  nextSlide: nextSlide,
                  direction: direction,
                });
              }
              return origSelect.apply(this, arguments);
            };
          }
        };
      });
      

      and use it like this:

      $scope.onSlideChanged = function (nextSlide, direction) {
          console.log('onSlideChanged:', direction, nextSlide);
      };
      

      and in html template:

      <carousel interval="myInterval" on-carousel-change="onSlideChanged(nextSlide, direction)">
      ...
      

    Hope this help : )

    0 讨论(0)
  • 2020-12-02 22:23

    AngularUI Bootstrap has changed naming conventions for controllers as thery have prefixed all of their controllers with prefix uib, so below is the updated solution of the original solution provided by runTarm:

    Angular:

    .directive('onCarouselChange', function($parse) {
        return {
            require: '^uibCarousel',
            link: function(scope, element, attrs, carouselCtrl) {
                var fn = $parse(attrs.onCarouselChange);
                var origSelect = carouselCtrl.select;
                carouselCtrl.select = function(nextSlide, direction, nextIndex) {
                    if (nextSlide !== this.currentSlide) {
                        fn(scope, {
                            nextSlide: nextSlide,
                            direction: direction,
                            nextIndex: this.indexOfSlide(nextSlide)
                        });
                    }
                    return origSelect.apply(this, arguments);
                };
            }
        };
    });
    

    Angular with TypeScript:

    module App.Directive {
    
        export class CarouselChange implements ng.IDirective {
    
            public require: string = '^uibCarousel';
    
            constructor(private $parse: ng.IParseService) { }
    
            public link: ng.IDirectiveLinkFn = (scope: ng.IScope, element: ng.IAugmentedJQuery, attributes: any, carouselCtrl: any) => {
                var fn = this.$parse(attributes.carouselChange);
                var origSelect = carouselCtrl.select;
                carouselCtrl.select = function(nextSlide, direction) {
                    if (nextSlide !== this.currentSlide) {
                        fn(scope, {
                            nextSlide: nextSlide,
                            direction: direction
                        });
                    }
                    return origSelect.apply(this, arguments);
                };
            }
    
            static Factory(): ng.IDirectiveFactory {
                var directive: ng.IDirectiveFactory = ($parse: ng.IParseService) => new CarouselChange($parse);
                directive['$inject'] = ["$parse"];
                return directive;
            }
        }
    }
    

    Thanks,

    0 讨论(0)
提交回复
热议问题