Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Applying angularjs ng-repeat to owl-carousel

<div class="owl-carousel">
    <div ng-repeat="items in itemlist"> 
        <a href="series.html"><img ng-src="{{items.imageUrl}}" /></a>
    </div>
    <div> 
      <a href="series.html"><img src="http://placehold.it/350x150" /></a>
    </div>
 </div>

View carousel here: Owl-carousel2

I'm running into an issue where whenever the ng-repeat directive is applied to carousel the items are stacked vertically instead of being layout horizontally.

If I leave out ng-repeat and use static items then it works as it should.

Is there a directive I can write and apply to owl-carousel to maintain the layout?

Also what is about ng-repeat that is causing the carousel to break?

Is angular somehow stripping the owl-carousel classes applied to the carousel?

Note* If build the list manually then iterate through and append the elements using :

var div = document.createElement('div');
var anchor = document.createElement('a');
var img = document.createElement('img');            
.....       
carousel.appendChild(div);

then call the owl.owlCarousel({..}) It works, not sure if this is the best work around because ng-repeat makes everything bit easier.

I discovered a hack , if I wrap the owl init in a timeout then ng-repat works.

setTimeout(function(){
      ...call owl init now  
},1000);

<link rel="stylesheet" href="css/owl.carousel.css"/>
<link rel="stylesheet" href="css/owl.theme.default.min.css"/>

.....
    <script src="/js/lib/owl.carousel.min.js"></script> 
        <script>
             $(document).ready(function() {
               var owl = $('.owl-carousel');
               owl.owlCarousel({
                 .....
               });
               owl.on('mousewheel', '.owl-stage', function(e) {
                 if (e.deltaY > 0) {
                   owl.trigger('next.owl');
                 } else {
                   owl.trigger('prev.owl');
                 }
                 e.preventDefault();
               });
             })

        </script>
like image 977
Fabii Avatar asked Jan 16 '15 16:01

Fabii


2 Answers

Was able to modify a directive from DTing on another post to get it working with multiple carousels on the same page. Here is a working plnkr

-- Edit -- Have another plnkr to give an example on how to add an item. Doing a reinit() did not work cause any time the owl carousel is destroyed it loses the data- elements and can never initialize again.

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="[email protected]" src="https://code.angularjs.org/1.3.15/angular.js" data-semver="1.3.15"></script>
    <script data-require="[email protected]" 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>
like image 143
JKOlaf Avatar answered Sep 20 '22 12:09

JKOlaf


I tried fiddling around with different directives but had no luck until I discovered this, it might a bit of a hack fix, but it works nonetheless.

Here is my div setup:

<div ng-repeat="item in mediaitems">
  <img ng-src="item.imageurl" />
</div>

$scope.mediaitems is generated using ajax call. I found that if I delayed the owl initialization until my list was populated then it would render it properly. Also if you decide you want update you list dynamically just call the setupcarousel function (look below) after the list has been populated and it will re-init the carousel.

Note that carousel init is in an external file within an anonymous function. That's just how I choosed to set it up, you can have yours in-line or however you please.

In my controller I had something like this :

$scope.populate = function(){
     $timeout(function(){   
      $scope.mediaitems  = returnedlist;   //list of items retrun from server
       utils.setupcarousel();              //call owl initialization
     });
};

var utils = (function(){
    var setupcarousel = function(){
        console.log('setting up carousel..');
         var owl = $('.owl-carousel');
         if(typeof owl.data('owlCarousel') != 'undefined'){
             owl.data('owlCarousel').destroy();
             owl.removeClass('owl-carousel');
         }

        owl.owlCarousel({
            loop: false,
            nav: true,
            margin: 10,
            responsive: {
              0: {items: 3 },
              600: {items: 5},
              960: { items: 8},
              1200:{items: 10},
              1600:{items: 12}
            }
          });
    };

    return{
      ....
    }

})();
like image 30
Fabii Avatar answered Sep 18 '22 12:09

Fabii