Search code examples
angularjsdata-bindingdirectiveangular-ngmodelion-range-slider

Dynamically update ion.rangeSlider ngModel in AngularJS directive


I'm trying to update the value of an Ion.RangeSlider when its bound ng-model scope variable changes. The model updates when the Ion.RangeSlider is used, but not vice-versa. Other inputs with the same ng-model update when the model value changes, so this must be some special case.

1

Edit: Woo! Here's a snippet @lin :) Also jsfiddle.

var app = angular.module('ngModelIonRangeSliderDemo', []);

app.controller('MainCtrl', function ($scope, $rootScope, $timeout) {
    
    $scope.someNumber = 10;
    
}).directive('ionRangeSlider', function ionRangeSlider() {
   return {
      restrict: 'A',
      scope: {
         rangeOptions: '=',
         model: '=ngModel'
      },
      link: function (scope, elem, attrs) {
         scope.$watch('model',function () {
            elem.ionRangeSlider(scope.rangeOptions);
         });
      }
   }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.10/angular.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/1.1.2/ui-bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ion-rangeslider/2.1.6/js/ion.rangeSlider.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ion-rangeslider/2.1.6/css/ion.rangeSlider.min.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ion-rangeslider/2.1.6/css/ion.rangeSlider.skinFlat.min.css" />

<div ng-app="ngModelIonRangeSliderDemo">
    <div ng-controller="MainCtrl" class="wrapper">
       <h3>Text input updates slider, but not vice-versa.</h3>
       <input ion-range-slider ng-model="someNumber" range-options="{min: -100, max: 100, step: .001}">
       <br/>
       <input type="text" ng-model="someNumber" class="form-control">
    </div>
</div>


I have tried all kinds of suggestions in over ten somewhat-related stack overflow posts (which is how I have set up the current scope.$watch scheme on the ngModel), but none have worked. There aren't any errors in my console. What's wrong? Also, why doesn't it work without any mention of the model in my directive? Please let me know if there's anything important I have failed to include in this post.


Solution

  • Just use slider.update() inside your directive and you will be fine:

    var app = angular.module('myApp', []);
    
    app.controller('MainCtrl', function ($scope, $rootScope, $timeout) {
    
        $scope.someNumber = 15;
        $scope.apply = false;
    
    }).directive('ionRangeSlider', function ionRangeSlider() {
       return {
          restrict: 'A',
          scope: {
             rangeOptions: '=',
             model: '=ngModel',
             apply: '=apply'
          },
          link: function (scope, elem, attrs) {
             elem.ionRangeSlider(scope.rangeOptions);
             scope.$watch('apply',function () {
              if (scope.apply) {
                scope.apply = false;
                var slider = elem.data("ionRangeSlider");            
                slider.update({
                   from: scope.model
                });
              }
             });
          }
       }
    });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.10/angular.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/1.1.2/ui-bootstrap.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/ion-rangeslider/2.1.6/js/ion.rangeSlider.js"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ion-rangeslider/2.1.6/css/ion.rangeSlider.min.css" />
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ion-rangeslider/2.1.6/css/ion.rangeSlider.skinFlat.min.css" />
    
    <div ng-app="myApp" ng-controller="MainCtrl" class="wrapper">
      <h3>Text input updates slider and vice-versa.</h3>
      <input ion-range-slider ng-model="someNumber" apply="apply" range-options="{min: -100, max: 100, step: .001}">
      <br/>
      <input type="text" ng-model="someNumber" class="form-control" ng-change="apply = true">
    </div>