MrD
MrD

Reputation: 2481

BxSlider and Angular js

If you are working with Angular, probably you will have case where you want to call some JQUERY library to do something for you. The usual way would be to call JQUERY function on page ready:

$(function(){
   $(element).someJqueryFunction();
});

If your element content is dynamically added using Angular, than this approach is not good as I understood, and you need to create an custom directive in order to fulfill this functionality.

In my case, I want to load bxSlider on <ul class="bxslider"> element, but content of the <ul> element should be loaded using angular ng-repeat directive.

Picture names are collected using REST service from the database.

I call my directive called startslider using the following code:

<div startslider></div> 

My custom Angular directive is: (pictures is variable in the $scope passed from my controller, which called REST service)

application.directive('startslider', function () {
    return {
        restrict: 'A',
        replace: false,
        template: '<ul class="bxslider">' +
                   '<li ng-repeat="picture in pictures">' +
                     '<img ng-src="{{siteURL}}/slide/{{picture.gallery_source}}" alt="" />'
                   '</li>' +
                  '</ul>',


        link: function (scope, elm, attrs) {//from angular documentation, the link: function should be called in order to change/update the dom elements
            elm.ready(function () {
                elm.bxSlider({
                    mode: 'fade',
                    autoControls: true,
                    slideWidth: 360,
                    slideHeight:600
                });




            });
        }
    };
});

As result, I get all the pictures from the database displayed on my screen, but without bxSlider loaded (all pictures displayed one bellow other).

Please note that bxSlider is working, because when I call $(element).bxSlider(); on manually written code, the slider loads.

Why is this happening?

Upvotes: 2

Views: 6553

Answers (3)

Mohsen
Mohsen

Reputation: 1422

this is the directive

.directive('slideit', function () {
return function (scope, elm, attrs) {
    var t = scope.$sliderData;

    scope.$watch(attrs.slideit, function (t) {
        var html = '';
        for (var i = 0; i <= t.length-1; i++) {
            html += '<li><ul class="BXslider"><li class="BXsliderHead"><img src="'+scope.$imageUrl+'flight/'+t[i].code+'.gif" />'+t[i].name+'</li><li class="BXsliderChild">'+t[i].noneStop+'</li><li class="BXsliderChild">'+t[i].oneStop+'</li><li class="BXsliderChild">'+t[i].twoStop+'</li></ul></li>';
        }
        angular.element(document).ready(function () {
            $("#" + $(elm[0]).attr('id')).html(html).bxSlider({

                pager:false,
                minSlides: 3,
                maxSlides: 7,
                slideWidth: 110,
                infiniteLoop: false,
                hideControlOnEnd: true,
                auto: false,
            });
        });
    });
};
});

this is the html in view

  <div ui-if="$sliderData">
        <ul id="experimental" slideit="$sliderData"></ul>
    </div>

and the important part is the dependency of js file

  <script src="/yii-application/frontend/web/js/libraries/angular/angular.min.js"></script>
  <script src="/yii-application/frontend/web/js/libraries/angular/angular-ui.js"></script>
 <script src="/yii-application/frontend/web/js/libraries/jquery/jquery-1.11.3.min.js"></script>
 <script src="/yii-application/frontend/web/js/libraries/flex/jquery.bxslider.min.js"></script>
 <script src="/yii-application/frontend/web/assets/e3dc96ac/js/bootstrap.min.js"></script>
 <script src="/yii-application/frontend/web/js/libraries/jquery-ui/jquery-ui.min.js"></script>
 <script src="/yii-application/frontend/web/js/searchResult.js"></script>
 <script src="/yii-application/frontend/web/js/Flight.js"></script>

and don't forget to put ui in module var app = angular.module('myApp', ['ui']);

this is the bxslider that i use !!!! maybe solve your problem

Upvotes: 0

chemoish
chemoish

Reputation: 1226

Not my solution, but I'd thought I would pass it along.

I like this solution the best (Utilizes directive controllers)

// slightly modified from jsfiddle

// bxSlider directive
controller: function() {},
link: function (scope, element, attrs, controller) {
    controller.initialize = function() {
        element.bxSlider(BX_SLIDER_OPTIONS);
    };
}

// bxSliderItem directive
require: '^bxSlider',
link: function(scope, element, attrs, controller) {
    if (scope.$last) {
        controller.initialize();
    }
}

http://jsfiddle.net/CaioToOn/Q5AcH/8/

Alternate, similar solution, using events (I do not like)

Jquery bxslider not working + Angular js ng-repeat issue

Root issue

  • You cannot call scope.$apply in the middle of a digest cycle.
  • You cannot fire bxSlider() until the template gets compiled.
  • Ultimately, you need to wait for the template to be compiled and available before calling bxSlider()

Calling a function when ng-repeat has finished

Upvotes: 0

Mihai Alex
Mihai Alex

Reputation: 678

EDIT: I think your problem is caused by trying to call the slider on HTMLUListElement, which is an object.

To call the slider on the DOM element, you could use $("." + $(elm[0]).attr('class')) that will use the existing bxslider class, or better assign an id to your <div startslider id="slideshow"></div> and call like $("." + $(elm[0]).attr('id'))

      elm.ready(function() {    
           $("." + $(elm[0]).attr('class')).bxSlider({
                mode: 'fade',
                autoControls: true,
                slideWidth: 360,
                slideHeight:600
           });
      });

Full code: http://jsfiddle.net/z27fJ/

Upvotes: 1

Related Questions