BxSlider и Angular js

Если вы работаете с Angular, возможно, у вас будет случай, когда вы захотите вызвать какую-нибудь библиотеку JQUERY, чтобы она что-то для вас сделала. Обычный способ - вызвать функцию JQUERY на готовой странице:

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

Если ваш element контент динамически добавляется с помощью Angular, то этот подход не очень хорош, как я понял, и вам нужно создать пользовательскую директиву, чтобы реализовать эту функциональность.

В моем случае я хочу загрузить bxSlider для элемента <ul class="bxslider">, но содержимое элемента <ul> должно быть загружено с использованием директивы angular ng-repeat.

Имена изображений собираются с помощью REST-сервиса из базы данных.

Я вызываю свою директиву startslider, используя следующий код:

<div startslider></div> 

Моя пользовательская директива Angular: (pictures является переменной в $scope, переданной от моего контроллера, который вызывает службу REST)

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
                });




            });
        }
    };
});

В результате я получаю все изображения из базы данных, отображаемые на моем экране, но без загруженного bxSlider (все изображения отображаются одно под другим).

Обратите внимание, что bxSlider работает, потому что когда я вызываю $(element).bxSlider(); для кода, написанного вручную, слайдер загружается.

Почему это происходит?


person MrD    schedule 30.03.2014    source источник


Ответы (3)


РЕДАКТИРОВАТЬ: я думаю, что ваша проблема вызвана попыткой вызвать ползунок в HTMLUListElement, который является объектом.

Чтобы вызвать ползунок в элементе DOM, вы можете использовать $("." + $(elm[0]).attr('class')), который будет использовать существующий класс bxslider, или лучше назначить идентификатор вашему <div startslider id="slideshow"></div> и вызывать как $("." + $(elm[0]).attr('id'))

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

Полный код: http://jsfiddle.net/z27fJ/

person Mihai Alex    schedule 30.03.2014
comment
Когда я вставляю scope.$apply(function() {scope.pictures= scope.startslider; }); Я получаю следующую ошибку: Ошибка: [$rootScope:inprog] errors.angularjs.org/1.3.0-beta.3/$rootScope/ - person MrD; 30.03.2014
comment
Загрузились все картинки, кроме одной ниже другой, как будто нет BxSlider. На самом деле не знаю, что происходит. - person MrD; 02.04.2014
comment
Вы проверили jsfiddle? Там есть рабочий пример. - person Mihai Alex; 02.04.2014
comment
Я также не могу отобразить правильный слайдер. Изображения складываются сверху вниз. Fiddle работает отлично, но не может интегрировать его в мой код. - person Kunal Kakkad; 26.07.2017

Не мое решение, но я думал, что передам его.

Мне больше всего нравится это решение (использует директивные контроллеры)

// 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/

Альтернативное, аналогичное решение, использующее события (мне не нравится)

Jquery bxslider не работает + проблема Angular js ng-repeat

Основная проблема

  • Вы не можете вызвать scope.$apply в середине цикла дайджеста.
  • Вы не можете запустить bxSlider(), пока шаблон не будет скомпилирован.
  • В конечном итоге вам нужно дождаться, пока шаблон будет скомпилирован и доступен, прежде чем вызывать bxSlider().

Вызов функции после завершения ng-repeat

person chemoish    schedule 16.06.2015

это директива

.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,
            });
        });
    });
};
});

это HTML в поле зрения

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

и важная часть - это зависимость файла js

  <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>

и не забудьте поместить пользовательский интерфейс в модуль var app = angular.module('myApp', ['ui']);

это bxslider, который я использую !!!! может решить вашу проблему

person Mohsen    schedule 10.08.2015