How to initialize the value of an input[range] usi

2019-08-29 10:47发布

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.

5条回答
Viruses.
2楼-- · 2019-08-29 11:36

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>

查看更多
迷人小祖宗
3楼-- · 2019-08-29 11:38

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)

查看更多
该账号已被封号
4楼-- · 2019-08-29 11:39

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.

查看更多
欢心
5楼-- · 2019-08-29 11:40

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.

查看更多
贪生不怕死
6楼-- · 2019-08-29 11:49

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>

查看更多
登录 后发表回答