Search code examples
javascriptjqueryangularjsangularjs-directiveuislider

how can i set the correct scope for ng-model in directive?


I have a simple directive to automate sliders:

app.directive('slider', function() {
    return {
        restrict: 'AE',
        link: function(scope, element, attrs) {
            element.slider({
                value: scope[attrs.ngModel],
                min: parseInt(attrs.min),
                max: parseInt(attrs.max),
                step: parseFloat(attrs.step),
                slide: function(event, ui) {
                    scope.$apply(function() {
                        scope[attrs.ngModel] = ui.value;
                    });
                }
            });
        }
    };
});

Simple scope set for different sliders:

$scope.sliders = [
    {type : 'red', value : 0},
    {type : 'green', value : 0},
]

HTML:

<div class="sliders" ng-repeat="slider in sliders">
    {{slider.value}}<slider min="1" max="10" step="1" ng-model="slider.value"></slider>
</div>

My problem is that my slider value isn't getting updated on slide...

DEMO: http://jsfiddle.net/ZXekc/641/

Slider Model isnt' updating


Solution

  • You can use the ngModelController to update the ng-model value

    var app = angular.module("app", []);
    
    app.controller("SomeController", function($scope) {
      $scope.sliders = [{
        type: 'red',
        value: 0
      }, {
        type: 'green',
        value: 0
      }, ];
    });
    
    app.directive("slider", function() {
      return {
        restrict: 'E',
        require: 'ngModel',
        link: function(scope, elem, attrs, ctrl) {
          $(elem).slider({
            range: false,
            min: parseInt(attrs['min']),
            max: parseInt(attrs['max']),
            step: parseFloat(attrs['step']),
            slide: function(event, ui) {
              scope.$apply(function() {
                ctrl.$setViewValue(ui.value)
              });
            }
          });
    
          ctrl.$render = function() {
            $(elem).slider("value", ctrl.$viewValue);
          };
        }
      }
    });
     slider {
       width: 200px;
       margin: 10px;
       display: block;
     }
    <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.1.1/angular.min.js"></script>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
    <script type="text/javascript" src="http://code.jquery.com/ui/1.10.2/jquery-ui.js"></script>
    <link rel="stylesheet" type="text/css" href="http://code.jquery.com/ui/1.10.2/themes/smoothness/jquery-ui.css" />
    
    <div ng-app="app">
      <div ng-controller="SomeController">
        Price: {{price}}
        <div class="sliders" ng-repeat="slider in sliders">
          {{slider.type}} = {{slider.value}}
          <slider min="1" max="10" step="1" ng-model="slider.value"></slider>
        </div>
        {{sliders | json}}
    
        <div>
          <input ng-repeat="slider in sliders" ng-model="slider.value" />
        </div>
      </div>
    </div>