2

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.

2
  • Could you create a fiddle or plnkr Matt? Commented Mar 5, 2017 at 8:04
  • Definitely! I haven't used them very many times, so it might take a bit :) Commented Mar 5, 2017 at 8:10

2 Answers 2

3

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>

Sign up to request clarification or add additional context in comments.

6 Comments

Perfect, thanks! I was concerned about the lag that appeared when clicking and sliding, but I discovered the model and $watch within the link function were not necessary with your fix, so I'll request an edit with all that's required in your answer for future readers.
@MattGoodrich But now the input model does not update the slider. Let me take a look at this.
Wow great catch.. As you definitely know now, it looks like both the model scope variable and $watch are necessary with your approach, but I'll keep trying too.
@MattGoodrich got it :) Check the updated code. I just added a simple switch handling by holding an trigger ng-change state.
Woo! Could you possibly explain what's happening if you have a sec please?
|
2

Extra demo, how binding ion.rangeSlider to input works:

http://jsfiddle.net/IonDen/r5aox84v/

var $range = $(".js-range-slider"),
    $inputFrom = $(".js-input-from"),
    $inputTo = $(".js-input-to"),
    instance,
    min = 0,
    max = 1000,
    from = 0,
    to = 0;

$range.ionRangeSlider({
    type: "double",
    min: min,
    max: max,
    from: 200,
    to: 800,
    onStart: updateInputs,
    onChange: updateInputs
});
instance = $range.data("ionRangeSlider");

function updateInputs (data) {
    from = data.from;
    to = data.to;

    $inputFrom.prop("value", from);
    $inputTo.prop("value", to); 
}

$inputFrom.on("input", function () {
    var val = $(this).prop("value");

    // validate
    if (val < min) {
        val = min;
    } else if (val > to) {
        val = to;
    }

    instance.update({
        from: val
    });
});

$inputTo.on("input", function () {
    var val = $(this).prop("value");

    // validate
    if (val < from) {
        val = from;
    } else if (val > max) {
        val = max;
    }

    instance.update({
        to: val
    });
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.