I try to initialize a slider using AngularJS, but the cursor show 100 when the value is over 100.
Setting the value 150 in a range [50,150] fails with this code :
<html ng-app="App">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script>
angular.module('App', ['App.controllers']);
angular.module('App.controllers', []).controller('AppController', function($scope) {
$scope.min = 50;
$scope.max = 150;
$scope.value = 150;
});
</script>
</head>
<body ng-controller="AppController" >
{{min}}<input ng-model="value" min="{{min}}" max="{{max}}" type="range" />{{max}}<br/>
value:{{value}}
</body>
</html>
The cursor is badly placed (it show 100 instead of 150).
How to display the cursor to its correct place ?
An explanation of what occurs could be on this forum
Update
This bug is reported as issue #6726
Update
The issue #14982 is closed by the Pull Request 14996 and solve the issue see answer.
After searches and tries , a possible way is to define a custom directive :
<html ng-app="App">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script>
angular.module('App', ['App.controllers']);
angular.module('App.controllers', []).controller('AppController', function($scope) {
$scope.min = 50;
$scope.max = 150;
$scope.value = 150;
}).directive('ngMin', function() {
return {
restrict: 'A',
require: 'ngModel',
link: function(scope, elem, attr) { elem.attr('min', attr.ngMin); }
};
}).directive('ngMax', function() {
return {
restrict: 'A',
require: 'ngModel',
link: function(scope, elem, attr) { elem.attr('max', attr.ngMax); }
};
});
</script>
</head>
<body ng-controller="AppController" >
{{min}}<input ng-model="value" ng-min="{{min}}" ng-max="{{max}}" type="range" />{{max}}<br/>
value:{{value}}
</body>
</html>
Even it is working this is a non standard extension in order to manage a very basic use case.
Try this new one.
You can configure angular to make it interpolate these values.
And you can use your initial code after that ...
Isn't it magic ?
Use this code only once in your app. Once angular is configured, it will be working for all the future ranges you will use.
<html ng-app="App">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script>
angular.module('App', ['App.controllers']);
angular.module('App.controllers', [])
/* Modify angular to make it interpolate min and max, for ngModel when type = range */
.config(['$provide', function($provide) {
$provide.decorator('ngModelDirective', ['$delegate', function($delegate) {
var ngModel = $delegate[0], controller = ngModel.controller;
ngModel.controller = ['$scope', '$element', '$attrs', '$injector', function(scope, element, attrs, $injector) {
if ('range' === attrs.type) {
var $interpolate = $injector.get('$interpolate');
attrs.$set('min', $interpolate(attrs.min || '')(scope));
attrs.$set('max', $interpolate(attrs.max || '')(scope));
$injector.invoke(controller, this, {
'$scope': scope,
'$element': element,
'$attrs': attrs
});
}
}];
return $delegate;
}]);
}])
.controller('AppController', function($scope) {
$scope.min = 50;
$scope.max = 150;
$scope.value = 150;
});
</script>
</head>
<body ng-controller="AppController" >
{{min}}<input ng-model="value" min="{{min}}" max="{{max}}" type="range"/>{{max}}<br/>
value:{{value}}
</body>
</html>
My lazy way of addressing this bug was to divide the min/max and step values by 100. So 300 becomes 3.0, etc. and values fall below 100. Then I multiply things back as needed.
From https://github.com/angular/angular.js/issues/6726 a possible way could be to differ the update of the value in a timer.
<html ng-app="App">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script>
angular.module('App', ['App.controllers']);
angular.module('App.controllers', []).controller('AppController', function($scope,$timeout) {
$scope.min = 50;
$scope.max = 150;
$timeout(function() {
$scope.value = 150;
});
});
</script>
</head>
<body ng-controller="AppController" >
{{min}}<input ng-model="value" min="{{min}}" max="{{max}}" type="range" />{{max}}<br/>
value:{{value}}
</body>
</html>
However it brings a useless complexity (especially when min,max and value are coming from a JSON REST API)
Since this commit, the initial code give the expected result.
Using release 1.6.0 allow to original code to show slider correctly :
<html ng-app="App">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.0/angular.min.js"></script>
<script>
angular.module('App', ['App.controllers']);
angular.module('App.controllers', []).controller('AppController', function($scope) {
$scope.min = 50;
$scope.max = 150;
$scope.value = 150;
});
</script>
</head>
<body ng-controller="AppController" >
{{min}}<input ng-model="value" min="{{min}}" max="{{max}}" type="range" />{{max}}<br/>
value:{{value}}
</body>
</html>