Kim
Kim

Reputation: 57

Angular UI Boostrap Carousel setting active slide after making new slides

I have a simple Carousel example. The example on Plnkr shows what I do in my application. I have to change the slides in my application. When I set the active slide after I change slides it goes to that slide and then slides out into oblivion or it goes to the first slide. How can I solve this problem? So that after making new slides I can go to the right slide?

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

angular.module('plunker', ['ui.bootstrap', 'ngTouch']);
    function CarouselDemoCtrl($scope) {
        $scope.genderPerson = "men";
        $scope.myInterval = -1;
        $scope.slides = [];

        $scope.$watch("genderPerson", function( newValue, oldValue ) {
            $scope.MakeSlides();
        });

        $scope.MakeSlides = function() {
            var newSlides = [];
            for ( var i = 0; i < 10; i++ ) {
                newSlides[i] = { image: 'http://api.randomuser.me/portraits/' + $scope.genderPerson + '/' + i + '.jpg' };
             }
             $scope.slides = newSlides;
             if ( $scope.slides[6] ) {
                 $scope.slides[6].active=true;
             }
        }
    }

Upvotes: 0

Views: 3389

Answers (2)

R. Kazeno
R. Kazeno

Reputation: 113

I just struggled with this problem. Here's my overly technical hack totally legit solution:

1. Create a new directive that overrides the addSlide method

.directive('onCarouselChange', function ($animate, $parse) {
    return {
        require: 'carousel',
        link: function (scope, element, attrs, carouselCtrl) {
            var origAdd = carouselCtrl.addSlide;
            carouselCtrl.addSlide = function(slide, element) {
                origAdd.apply(this, arguments);
                $animate.on('enter', element, function (elem, phase) {
                    if (phase === 'close') {
                        scope.$emit('carouselEntered');
                    }
                });
            };
        }
    };
})

This will emit an event when the carousel's ngRepeat has finished parsing its new elements.

2. Add the new directive to the carousel element

<carousel interval="myInterval" on-carousel-change>

3. Set the active slide on an event listener

Add an event listener to the function where you add the elements, and set the active slide on its callback

$scope.MakeSlides = function() {
    var newSlides = [];
    for ( var i = 0; i < 10; i++ ) {
        newSlides[i] = { image: 'http://api.randomuser.me/portraits/' + $scope.genderPerson + '/' + i + '.jpg' };
    }
    $scope.slides = newSlides;
    var dereg = $scope.$on('carouselEntered', function(event, data) {
        if ($scope.slides[6]) {
            $timeout(function () {
                $scope.slides[6].active=true;
            });
            dereg();
        }
    });
}

All of this is possible thanks to the magic of $animate's events.

Upvotes: 0

Rob J
Rob J

Reputation: 6629

Looks like there is a race condition, if I wrap the active slide set in a timeout with a delay it seems to work:

  $timeout(function () {
    $scope.slides[6].active=true;
  }, 100);

Upvotes: 2

Related Questions