1

I'm trying to get owl carousel to work in Angular.

I want to markup like this in my view, since I have many galleries :

<owl-carousel owl-options="owlOptions">
  <div ng-repeat="image in gallery" class="item">
    <p>hello</p>
  </div>
</owl-carousel>

Basically all the directive should be doing is initalizing the carousel. The directive works perfectly, unless I use an ng-repeat. I'm guessing the directive is loading before the ng-repeat is being processed.

Does anyone have any ideas on how to solve this without building templates and directives for every style of slider?

Thank you so much!

Here is the directive:

angular.module('dir.owlCarousel', [])
  .directive('owlCarousel',[function() {
    return {
      restrict: 'EA',
      transclude: false,
      scope: {
        owlOptions: '='
      },

      link: function(scope, element, attrs) {
        $(element).owlCarousel(scope.owlOptions);
      }

    };
  }]);
New Dev
  • 48,427
  • 12
  • 87
  • 129
Josh Meads
  • 151
  • 1
  • 7
  • can you describe what is actually happening when using `ng-repeat`? making a guess at the problem is ok, but not verifiable without expected and actual results. – Claies Mar 20 '15 at 01:03
  • I get the list of the repeated items, however they do not initiate into the slider. If I just list the items without ng-repeat then it will init into the slider. I think the ng-repeat is running after the slider directive has tried to init (and found nothing). – Josh Meads Mar 20 '15 at 01:05

2 Answers2

8

You want to take a look at these answer:

ng-repeat finish event

AngularJS event for when model binding or ng-repeat is complete?

angular.module('dir.owlCarousel', [])
  .directive('owlCarousel',[function() {
    return {
      restrict: 'EA',
      transclude: false,
      scope: {
        owlOptions: '='
      },
      link: function(scope, element, attrs) {
          scope.initCarousel = function() {
            $(element).owlCarousel(scope.owlOptions);
          };
        }
      }
    };
  }])
  .directive('owlCarouselItem',[function() {
     return function(scope) {
     if (scope.$last) {
        scope.initCarousel();
     }
    };
  }]);

<owl-carousel owl-options="owlOptions">
  <div owl-carousel-item ng-repeat="image in gallery" class="item">
    <p>hello</p>
  </div>
</owl-carousel>
Community
  • 1
  • 1
dting
  • 38,604
  • 10
  • 95
  • 114
  • 1
    @DTing, One correction: you need you move the `link:` function outside of the local scope in the `owlCarousel` directive. – Aaron Jessen Mar 23 '15 at 14:00
  • @DTing , i'm using your solution only with each item being added to the object repeated by GET requests(one for each item and then i `push` it). the problem is that `scope.$last` is `true` on the very first one(and also on all the rest), and when it is called a second time, all the items won't go inside the carousel [like so](https://github.com/OwlFonk/OwlCarousel/issues/179#issuecomment-224957000) what can i do? – FireBrand Jun 09 '16 at 17:17
  • Tried this and i'm getting TypeError: scope.initCarousel is not a function – Joram Clervius Dec 01 '16 at 17:32
  • How can this be done with multiple ng-repeats? I have to loop through two different arrays, 1 with videos 1 with images and I want them all in the same carousel. – Zack Herbert Aug 08 '17 at 21:59
  • btw you can safely remove the transclude property on the directives. its false by default – Crhistian Ramirez Oct 19 '17 at 18:17
8

Had to make some changes to your directive so it would work with multiple carousels on the same page. Here is a link to a working plnkr

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope) {
  $scope.items1 = [1,2,3,4,5];
  $scope.items2 = [1,2,3,4,5,6,7,8,9,10];
}).directive("owlCarousel", function() {
    return {
        restrict: 'E',
        transclude: false,
        link: function (scope) {
            scope.initCarousel = function(element) {
              // provide any default options you want
                var defaultOptions = {
                };
                var customOptions = scope.$eval($(element).attr('data-options'));
                // combine the two options objects
                for(var key in customOptions) {
                    defaultOptions[key] = customOptions[key];
                }
                // init carousel
                $(element).owlCarousel(defaultOptions);
            };
        }
    };
})
.directive('owlCarouselItem', [function() {
    return {
        restrict: 'A',
        transclude: false,
        link: function(scope, element) {
          // wait for the last item in the ng-repeat then call init
            if(scope.$last) {
                scope.initCarousel(element.parent());
            }
        }
    };
}]);

Here is the HTML

<!DOCTYPE html>
<html ng-app="plunker">

  <head>
    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <script>document.write('<base href="' + document.location + '" />');</script>
    <link rel="stylesheet" href="style.css" />
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/owl-carousel/1.3.3/owl.carousel.min.css" />
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/owl-carousel/1.3.3/owl.theme.min.css" />
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/owl-carousel/1.3.3/owl.transitions.min.css" />
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/owl-carousel/1.3.3/owl.carousel.min.js" />
    <script data-require="angular.js@1.3.x" src="https://code.angularjs.org/1.3.15/angular.js" data-semver="1.3.15"></script>
    <script data-require="jquery@2.1.3" data-semver="2.1.3" src="http://code.jquery.com/jquery-2.1.3.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/owl-carousel/1.3.3/owl.carousel.min.js"></script>
    <script src="app.js"></script>
  </head>

  <body ng-controller="MainCtrl">
    <data-owl-carousel class="owl-carousel" data-options="{navigation: true, pagination: false, rewindNav : false}">
      <div owl-carousel-item="" ng-repeat="item in ::items1" class="item">
        <p>{{::item}}</p>
      </div>
    </data-owl-carousel>
    <data-owl-carousel class="owl-carousel" data-options="{navigation: false, pagination: true, rewindNav : false}">
      <div owl-carousel-item="" ng-repeat="item in ::items2" class="item">
        <p>{{::item}}</p>
      </div>
    </data-owl-carousel>
  </body>

</html>
JKOlaf
  • 475
  • 5
  • 6