AngularUi jQuery Passthrough - метод вызова для получения значения плагина

Я использую AngularJS, сквозной переход jQuery AngularUI uiJq и jQuery noUiSlider, но на самом деле вопрос касается доступа к методу. Часть html правильно отображает ползунок, и мне нужно выполнить двустороннюю привязку к выходному значению ползунка. Я безуспешно пробовал приведенный ниже код javascript и его варианты в контроллере.

Похоже, uiJq не работает со всеми плагинами jQuery. Мне интересно, не работает ли noUiSlider, и мне нужно написать пользовательскую директиву. Также не уверен, нужно ли мне иметь дело с отложенным выполнением или нужно uiRefresh вручную $watch что-то делать.

HTML

<div class="noUiSlider" id="abc" ui-jq="noUiSlider"
    ui-options="{range: [0, 100], start: 50, handles: 1}"></div>

JS

app.controller('MainCtrl', function ($scope) {
    $scope.selectionValue = $('#abc').noUiSlider().val();
    // error, seems to override whatever is in html
    $scope.selectionValue = $('#abc').val();
    // no error but no value is returned
});

Спасибо!


person Ray Shan    schedule 07.05.2013    source источник


Ответы (2)


Итак, вы сталкиваетесь с множеством разных проблем одновременно, и вам трудно понять, с чего начать. ВО-ПЕРВЫХ прочтите это: https://github.com/angular/angular.js/wiki/Understanding-Directives

Во-вторых, НЕ используйте jQuery в своем контроллере. Контроллер срабатывает ОДИН РАЗ и срабатывает ДО того, как шаблон «рендерится». Это означает, что вы извлекаете значения DOM до того, как они были инициализированы (или даже существовали), и вы получаете сообщение об ошибке, поскольку .noUiSlider() никогда не выполнялось для элемента DOM.

Вы должны думать АСИНХРОННО, когда дело доходит до AngularJS. Шаблоны постоянно меняются, обновляются и обновляются, и вы должны кодировать с учетом этого ожидания.

В любом случае, короче говоря, вам лучше использовать функцию обратного вызова слайда для обновления модели, хотя это немного хакерски, и если вы не против намочить нос, вы можете попробовать создать новую директиву вообще, которая requires: 'ngModel'

ui-options="{range, [0,100], start: 50, handles: 1, slide: slideCallback }"
...
$scope.slideCallback = function() {
  $scope.myModel = $(this).val();

  // this tells angular to refresh since an async event occurred outside of angular
  $scope.$apply(); 
};
person ProLoser    schedule 08.05.2013
comment
Спасибо за это и всю вашу работу над всем, что связано с Angular. Вы правы. Легко просто использовать существующие компоненты, но я напишу правильную директиву ползунка в стиле Angular (если все смогут просто перейти на IE10, чтобы я мог использовать HTML5 range...) - person Ray Shan; 08.05.2013
comment
Ценный ответ :). Спасибо ! - person kaushik gandhi; 05.11.2014

Вот быстрая грязная директива, которая обертывает JQuery UI Slider. Просто установите ngModel, как всегда, для двунаправленной привязки, и добавьте атрибуты минимальной максимальной ориентации и анимации в тег директивы.

Пример использования:

<div si-slider ng-model="TargetModel.SomeIntProperty" min="100" max="2000" orientation="horizontal" animate="true"></div>

И код:

var directives = angular.module('si.directives', []);    
directives.directive('siSlider', function ($rootScope) {
    var directiveDefinitionObject = {
        restrict: 'EA',
        transclude: 'false',
        template: '<div class="slider"></div>',
        replace: true,
        scope: { Model:"=ngModel"},
        link: function (scope, element, attrs) {
            var change = function () {
                scope.Model = (element).slider("value");
                if (!$rootScope.$$phase) {
                    scope.$apply();
                }
            };
            element.slider({
                value: scope.Model,
                animate: attrs.animate,
                orientation: attrs.orientation,
                min: parseInt(attrs.min, 10),
                max: parseInt(attrs.max, 10),
                slide: change,
                change: change
            });
            scope.$watch('Model', function (value) {
                element.slider("value", value);
            });
        }
    };

    return directiveDefinitionObject;
});
person Jason    schedule 22.05.2013