57

I am trying to use simple jQuery UI. I've included everything and I have this simple script:

<script>
  $(function() {
    $( "#slider" ).slider();
  });
</script>

and

<div id="slider"></div>

My includes:

<script type="text/javascript" src="js/jquery-1.10.2.js"></script>
<script type="text/javascript" src="js/jquery-ui-1.10.4.custom.min.js"></script>
<script type="text/javascript" src="js/jquery.easing.1.3.js"></script>
<script type="text/javascript" src="js/ayaSlider.js"></script>
<script type="text/javascript" src="js/bootstrap.min.js"></script>
<script type="text/javascript" src="js/angular.min.js"></script>
<script type="text/javascript" src="js/angular-route.min.js"></script>
<script type="text/javascript" src="js/app.js"></script>

But when I am opening the page there is no slider. According to documentation of angular:

If jQuery is available, angular.element is an alias for the jQuery function. If jQuery is not available, angular.element delegates to Angular's built-in subset of jQuery.

However, I don't really understand how can I use angular.element and there is no example.

Update: I managed to have the slider on the screen but it does not work, I cannot change values or do something with it.

enter image description here

11
  • 2
    if you included jQuery, you can just use it normally. Are you getting any errors in your console?
    – Nick
    Commented Mar 26, 2014 at 15:49
  • execute .slider() when the dom is ready Commented Mar 26, 2014 at 15:50
  • 1
    @Dreamwalker, the questioner already does so. Commented Mar 26, 2014 at 15:51
  • @user, also keep in mind that jQuery UI requires a CSS file to be included in order to work properly. Double-check you have included that file in your page. Commented Mar 26, 2014 at 15:51
  • @Nick No I am not getting any error. I updated the post with my includes list. Commented Mar 26, 2014 at 15:52

4 Answers 4

45

Ideally you would put that in a directive, but you can also just put it in the controller. http://jsfiddle.net/tnq86/15/

  angular.module('App', [])
    .controller('AppCtrl', function ($scope) {

      $scope.model = 0;

      $scope.initSlider = function () {
          $(function () {
            // wait till load event fires so all resources are available
              $scope.$slider = $('#slider').slider({
                  slide: $scope.onSlide
              });
          });

          $scope.onSlide = function (e, ui) {
             $scope.model = ui.value;
             $scope.$digest();
          };
      };

      $scope.initSlider();
  });

The directive approach:

HTML

<div slider></div>

JS

  angular.module('App', [])
    .directive('slider', function (DataModel) {
      return {
         restrict: 'A',
         scope: true,
         controller: function ($scope, $element, $attrs) {
            $scope.onSlide = function (e, ui) {
              $scope.model = ui.value;
              // or set it on the model
              // DataModel.model = ui.value;
              // add to angular digest cycle
              $scope.$digest();
            };
         },
         link: function (scope, el, attrs) {

            var options = {
              slide: scope.onSlide  
            };

            // set up slider on load
            angular.element(document).ready(function () {
              scope.$slider = $(el).slider(options);
            });
         }
      }
  });

I would also recommend checking out Angular Bootstrap's source code: https://github.com/angular-ui/bootstrap/blob/master/src/tooltip/tooltip.js

You can also use a factory to create the directive. This gives you ultimate flexibility to integrate services around it and whatever dependencies you need.

3
  • Using jQuery doesn't necessarily mean things will get messy, it's usually due to poor structure of the code. Ideally you'd want to build out an api within a service using whatever you need and then call those methods within your directive.
    – Cameron
    Commented Jul 6, 2015 at 19:24
  • 1
    angular.element(document).ready(function () { scope.$slider = $(el).slider(options); }); did the trick for me. thanks Commented Sep 8, 2015 at 17:34
  • How this will be in angular4? Commented Oct 31, 2017 at 9:30
8

This should be working. Please have a look at this fiddle.

$(function() {
   $( "#slider" ).slider();
});//Links to jsfiddle must be accompanied by code

Make sure you're loading the libraries in this order: jQuery, jQuery UI CSS, jQuery UI, AngularJS.

4
  • You're not loading the libraries in that order. I supposed you'd need/want to load angular and dependencies before jQuery Commented Mar 26, 2014 at 16:29
  • @user23236245242 as far as I can tell the fiddle shows exactly what you want. Plus here I added AngularJS to External Resources and it works fine. Take a look at the source-code here.
    – Eugene
    Commented Mar 26, 2014 at 16:30
  • 3
    I meant "The code you posted should be working", provided that you load the libraries in the right order.
    – Alethes
    Commented Mar 26, 2014 at 16:34
  • This is simple and fine...why not to use this technique instead of the complicated accepted one ?
    – TOPKAT
    Commented Mar 30, 2016 at 14:33
2

You have to do binding in a directive. Look at this:

angular.module('ng', []).
directive('sliderRange', function($parse, $timeout){
    return {
        restrict: 'A',
        replace: true,
        transclude: false,
        compile: function(element, attrs) {            
            var html = '<div class="slider-range"></div>';
            var slider = $(html);
            element.replaceWith(slider);
            var getterLeft = $parse(attrs.ngModelLeft), setterLeft = getterLeft.assign;
            var getterRight = $parse(attrs.ngModelRight), setterRight = getterRight.assign;

            return function (scope, slider, attrs, controller) {
                var vsLeft = getterLeft(scope), vsRight = getterRight(scope), f = vsLeft || 0, t = vsRight || 10;                        

                var processChange = function() {
                    var vs = slider.slider("values"), f = vs[0], t = vs[1];                                        
                    setterLeft(scope, f);
                    setterRight(scope, t);                    
                }                 
                slider.slider({
                    range: true,
                    min: 0,
                    max: 10,
                    step: 1,
                    change: function() { setTimeout(function () { scope.$apply(processChange); }, 1) }
                }).slider("values", [f, t]);                    
            };            
        }
    };
});

This shows you an example of a slider range, done with jQuery UI. Example usage:

<div slider-range ng-model-left="question.properties.range_from" ng-model-right="question.properties.range_to"></div>
1

The best option is create a directive and wrap the slider features there. The secret is use $timeout, the jquery code will be called only when DOM is ready.

angular.module('app')
.directive('my-slider', 
    ['$timeout', function($timeout) {
        return {
            restrict:'E',
            scope: true,
            template: '<div id="{{ id }}"></div>',
            link: function($scope) {
                $scope.id = String(Math.random()).substr(2, 8);

                $timeout(function() {
                    angular.element('#'+$scope.id).slider();                    
                });
            }
        };
    }]
);

Not the answer you're looking for? Browse other questions tagged or ask your own question.