Search code examples
jqueryjsonajaxowl-carouselowl-carousel-2

Owl carousel 2 dynamic content JSON


I have a problem with displaying dynamic content with Owl carousel 2 using JSON/AJAX. I get no error messages in console, but cant get the carousel to work. I only see a blank page. I am able to append the image url's fetched from JSON file with jquery.append, but they wont be shown in the carousel that way. Displays are set to "block". Any tips what am i missing?

index.html -

<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Rengastie</title>
    <link rel="stylesheet" href="css/app.css">
    <link rel="stylesheet" href="css/owl.carousel.min.css">
    <link rel="stylesheet" href="css/owl.theme.default.min.css">
    <link rel="stylesheet" href="css/style.css">

  </head>
  <body>

    <div class="row">
      <div class="small-12 columns">
        <div id="top-carousel" class="owl-carousel owl-theme">

        </div>
    </div>
  </div>

    <script src="https://code.jquery.com/jquery-1.9.1.min.js"></script>
    <script src="js/owl.carousel.min.js"></script>
    <script src="js/app.js"></script>

  </body>
</html>

app.js -

$(document).ready(function() {
    $('.owl-carousel').owlCarousel();

});

var $owl = $('.owl-carousel');

$owl.owlCarousel({
          loop:true,
          items: 1,
          autoplay:true,
          autoplayTimeout:3000,
          autoplayHoverPause:false
}); 

$.ajax({
  url: 'json/data.json',
  dataType: 'json',
  success: function(data) {
    var content = '';
    var alt = "pic123";
    for (i in data.owl) {
            content += "<div class='item'><img src=\"" +data.owl[i].img+ "\" alt=\"" +alt+ "\"></div>";
        }

    $owl.trigger('insertContent.owl',content);
    //$owl.append(content); This stacks the images above eachother, not affected by the carousel settings
  }
});

data.json -

{
  "owl" : [
    {
      "img": "img/kuvaIso1.jpg"
    },
    {
      "img": "img/kuvaIso2.jpg"
    },
    {
      "img": "img/kuvaIso3.jpg"
    },
    {
      "img": "img/kuvaIso4.jpg"
    },
    {
      "img": "img/kuvaIso5.jpg"
    }
  ]
}

Solution

  • As of version 2.0.0 owlcarousel doesn't support item loading from json data anymore. But they indeed support custom plugins to interact with the core on the fly. I needed to develop a plugin to achieve this. Here is the code.

    /**
     * Owl Carousel JSON load plugin
     * @since 2.0.0
     * @author maksbd19 
     * @link http://stackoverflow.com/questions/35838983/
     */
    
    ;(function ( $, window, document, undefined ) {
    
        var Insatances =  undefined;
    
        var JSONload = function(carousel){
    
        this._core = carousel;
    
        this.options = {};
    
        this._handlers = {
            'initialized.owl.carousel': $.proxy(function(e) {
                if (!e.namespace || !this._core.settings || !this._core.settings.path) {
                    return;
                }
    
                Insatances = Insatances || [];
    
                if( !pathExists(this._core.settings.path, Instances) ){
                    Instances.push({
                        path: this._core.settings.path,
                        onSuccess: this._core.settings.onSuccess,
                        onError: this._core.settings.onError,
                        loading: false
                    });
                }
    
                for( var i in Instances ){
                    if( Instances.hasOwnProperty(i) && Instances[i].path != '' && !Instances[i].loading ){
    
                        Instances[i].loading = true;
    
                        $.getJSON(Instances[i].path, $.proxy(function (data) {
                            if (typeof Instances[i].onSuccess === "function") {
                                Instances[i].onSuccess.call(this, data);
                            }
                        }, this)).fail($.proxy(function (data) {
                            if (typeof Instances[i].onError === "function") {
                                Instances[i].onError.apply(this, [data]);
                            }
                        }, this));
                    }
                }
    
                function pathExists(path, instance){
                    if(instance.length == 0){
                        return false;
                    }
                    for( var i=0; i<instance.length; i++ ){
                        if( instance[i].path == path ){
                            return true;
                        }
                    }
    
                    return false;
                }
    
            }, this)
        };
    
        this.options = $.extend(JSONload.Defaults, this._core.options);
        this._core.$element.on(this._handlers);
    }
    
    JSONload.Defaults = {
        path: '',
        onSuccess:'',
        onError:''
    };
    
    $.fn.owlCarousel.Constructor.Plugins['JSONload'] = JSONload;
    })( window.Zepto || window.jQuery, window,  document );
    

    And to use this-

    var OC = $("#owl-demo-featured").owlCarousel({
        path : 'path/to/json',
        onSuccess : function(r){
            if( r.length > 0 ){
    
                for( var i in r ){
                    if( r.hasOwnProperty(i) ){
                        var $html = '';
                        // process you data with the template you want inject
                        OC.trigger('add.owl.carousel', jQuery($html) )
                    }
                }
                OC.trigger('refresh.owl.carousel')
            }
        },
        onError: function(r){
            console.error(r);
        }
    });
    

    This is a very minimalistic approach to get the job done. You need to modify as per you need.

    I hope this will help you.

    Update

    Just noticed a strange thing with this process. It seems Owlcarousel loads its plugins in somewhat singleton pattern. So if there were multiple instances of carousel in a page then only the last one was being updated. I think its for the asynchronous behaviour of $.getJSON() but I'm not sure. Anyway I made a work around to comply