AngularJS - 输入数字微调器,手动输入数字时无法正常工作
AngularJS - input number spinner, not working correctly when number is inputted manually
我在 Whosebug 上找到了一个用户为 angularJS 制作的指令,用于输入数字微调器,我正在寻找它!
一切正常,但有一件事不是,当你在输入字段中手动输入一个数字,然后按减号,它会从该数字中减去 1,这里一切正常,
但是当您输入一个数字并首先按下加号时,它不会加 1,而是会在您输入的数字旁边添加一个 "1"
!
修复后只去 "minus",
有人可以帮我修复代码以避免这种情况吗?我希望当我手动输入号码时,您可以按 "plus" 并在该号码上获得 +1
!
那是因为 input type="text"
will return a string as a model value, and as was mentioned by @AlekseySolovey - you'll have to cast it to a Number(因为 "10" + 1
结果会给你“101”)。由于您也在使用 numericOnly
指令,因此它似乎是进行转换的正确位置,因为您只会在一个地方挥手进行转换。这是一个例子:
(function () {
"use strict";
var app = angular
.module("app", []);
app.controller('AppController', ['$scope', function ($scope) {
var vm = this;
vm.testNumber = 10;
}]);
app.directive('numericOnly', function () {
return {
require: 'ngModel',
link: function (scope, element, attrs, modelCtrl) {
modelCtrl.$parsers.push(function (inputValue) {
if (angular.isNumber(inputValue)) {
return inputValue;
}
var transformedInput = inputValue ? Number(inputValue.replace(/[^\d.-]/g, '')) : null;
if (transformedInput != inputValue) {
modelCtrl.$setViewValue(transformedInput);
modelCtrl.$render();
}
return transformedInput;
});
}
};
});
app.directive('numberSpin', [function () {
return {
restrict: 'E',
scope: {
"ngModel": '='
},
template: '<div>' +
'<input numeric-only data-ng-model="ngModel" ng-pattern="onlyNumbers" type="text">' +
'<a class="ns-plus" data-ng-click="plus()">+</a>' +
'<a class="ns-minus"data-ng-click="minus()">-</a> </div>',
link: function (scope, elem, attrs) {
scope.onlyNumbers = /^\d+$/;
scope.plus = function () {
scope.ngModel = scope.ngModel + 1;
};
scope.minus = function () {
scope.ngModel = scope.ngModel - 1;
};
}
}
}])
}());
number-spin div {
position: relative;
width: 126px;
}
number-spin input {
height: 32px;
width: 100%;
text-align: right;
padding-right: 20px;
box-sizing: border-box;
font-size: 16px;
}
number-spin .ns-plus {
position: absolute;
text-align: center;
line-height: 16px;
top: 0;
right: 0;
height: 16px;
display: block;
border-left: 1px solid #ccc;
border-bottom: 1px solid #ccc;
width: 16px;
}
number-spin .ns-minus {
position: absolute;
text-align: center;
display: block;
line-height: 16px;
height: 16px;
border-left: 1px solid #ccc;
bottom: 0;
right: 0;
width: 16px;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.2/angular.min.js"></script>
<div ng-app="app" style="padding: 16px; "data-ng-controller="AppController as vm">
<number-spin data-ng-model="vm.testNumber"></number-spin>
</div>
更新: 允许将 min
/max
传递到指令中的更简单的代码:
(function () {
"use strict";
var app = angular
.module("app", []);
app.controller('AppController', ['$scope', function ($scope) {
var vm = this;
vm.testNumber = 10;
}]);
app.directive('numberSpin', [function () {
return {
restrict: 'E',
scope: {
"ngModel": '=',
"min": '<',
"max": '<',
"step": '<'
},
template: '<div>' +
'<input data-ng-model="ngModel" type="number" ng-attr-min="{{min}}" ng-attr-max="{{max}}">' +
'<a class="btn ns-plus" data-ng-click="plus()">+</a>' +
'<a class="btn ns-minus"data-ng-click="minus()">-</a> </div>',
link: function (scope, elem, attrs) {
scope.plus = function () {
if (scope.ngModel >= scope.max) return;
scope.ngModel += (scope.step || 1);
checkModel()
};
scope.minus = function () {
if (scope.ngModel <= scope.min) return;
scope.ngModel -= (scope.step || 1);
checkModel();
};
function checkModel() {
if (!scope.ngModel) scope.ngModel = scope.min || 0;
}
}
}
}])
}());
number-spin div {
position: relative;
width: 126px;
}
number-spin input {
height: 32px;
width: 100%;
text-align: right;
padding-right: 20px;
box-sizing: border-box;
font-size: 16px;
}
number-spin .btn {
position: absolute;
text-align: center;
line-height: 16px;
display: block;
height: 16px;
right: 0;
border-left: 1px solid #ccc;
width: 16px;
cursor: pointer;
user-select: none;
}
number-spin .ns-plus {
top: 0;
border-bottom: 1px solid #ccc;
cursor: pointer;
user-select: none;
}
number-spin .ns-minus {
bottom: 0;
}
number-spin input[type=number]::-webkit-inner-spin-button,
number-spin input[type=number]::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.2/angular.min.js"></script>
<div ng-app="app" style="padding: 16px; "data-ng-controller="AppController as vm">
<number-spin data-ng-model="vm.testNumber" min="0" max="15"></number-spin>
</div>
(function () {
"use strict";
var app = angular.module("app", ['tien.stepInput']);
app.controller('AppController', function ($scope) {
$scope.demo = 10
$scope.options = {
min_value: 1,
overrides: [
{value: 1, style: 'danger', view_value: '<i class="fa fa-times"></i>'},
{value: 0, style: 'warning', view_value: '<i class="fa fa-question"></i>'}
]
};
});
}());
.tien-step {
display: inline-block;
height: 24px;
width: 93px; }
.tien-step button, .tien-step .step-value {
border: none;
float: left;
height: 24px;
text-align: center; }
.tien-step button:focus, .tien-step button:active, .tien-step button:focus:active, .tien-step .step-value:focus, .tien-step .step-value:active, .tien-step .step-value:focus:active {
outline: none; }
.tien-step button {
background: transparent;
color: white;
line-height: 24px;
width: 24px; }
.tien-step .step-value {
border-bottom: 1px solid transparent;
border-top: 1px solid transparent;
font-size: 18px;
line-heigth: 22px;
padding: 0;
width: 45px; }
.tien-step.primary button {
background: #428bca; }
.tien-step.primary button:active {
background: #3071a9; }
.tien-step.primary button.disabled {
opacity: 0.8; }
.tien-step.primary button.disabled:active {
background: #428bca; }
.tien-step.primary .step-value {
border-color: #428bca; }
.tien-step.primary .step-value i.fa {
color: #428bca;
font-size: 14px;
line-height: 20px;
top: -2px;
position: relative; }
.tien-step.success button {
background: #5cb85c; }
.tien-step.success button:active {
background: #449d44; }
.tien-step.success button.disabled {
opacity: 0.8; }
.tien-step.success button.disabled:active {
background: #5cb85c; }
.tien-step.success .step-value {
border-color: #5cb85c; }
.tien-step.success .step-value i.fa {
color: #5cb85c;
font-size: 14px;
line-height: 20px;
top: -2px;
position: relative; }
.tien-step.info button {
background: #5bc0de; }
.tien-step.info button:active {
background: #31b0d5; }
.tien-step.info button.disabled {
opacity: 0.8; }
.tien-step.info button.disabled:active {
background: #5bc0de; }
.tien-step.info .step-value {
border-color: #5bc0de; }
.tien-step.info .step-value i.fa {
color: #5bc0de;
font-size: 14px;
line-height: 20px;
top: -2px;
position: relative; }
.tien-step.warning button {
background: #f0ad4e; }
.tien-step.warning button:active {
background: #ec971f; }
.tien-step.warning button.disabled {
opacity: 0.8; }
.tien-step.warning button.disabled:active {
background: #f0ad4e; }
.tien-step.warning .step-value {
border-color: #f0ad4e; }
.tien-step.warning .step-value i.fa {
color: #f0ad4e;
font-size: 14px;
line-height: 20px;
top: -2px;
position: relative; }
.tien-step.danger button {
background: #d9534f; }
.tien-step.danger button:active {
background: #c9302c; }
.tien-step.danger button.disabled {
opacity: 0.8; }
.tien-step.danger button.disabled:active {
background: #d9534f; }
.tien-step.danger .step-value {
border-color: #d9534f; }
.tien-step.danger .step-value i.fa {
color: #d9534f;
font-size: 14px;
line-height: 20px;
top: -2px;
position: relative; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.22/angular.min.js"></script>
<script src="http://angular-step-input.10kb.nl/angular-step-input.min.js"></script>
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet">
<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.1.0/css/font-awesome.min.css" rel="stylesheet">
<div ng-app="app" ng-controller="AppController">
<tien-step-input ng-model="demo"></tien-input-step>
</div>
我在 Whosebug 上找到了一个用户为 angularJS 制作的指令,用于输入数字微调器,我正在寻找它!
一切正常,但有一件事不是,当你在输入字段中手动输入一个数字,然后按减号,它会从该数字中减去 1,这里一切正常,
但是当您输入一个数字并首先按下加号时,它不会加 1,而是会在您输入的数字旁边添加一个 "1"
!
修复后只去 "minus",
有人可以帮我修复代码以避免这种情况吗?我希望当我手动输入号码时,您可以按 "plus" 并在该号码上获得 +1
!
那是因为 input type="text"
will return a string as a model value, and as was mentioned by @AlekseySolovey - you'll have to cast it to a Number(因为 "10" + 1
结果会给你“101”)。由于您也在使用 numericOnly
指令,因此它似乎是进行转换的正确位置,因为您只会在一个地方挥手进行转换。这是一个例子:
(function () {
"use strict";
var app = angular
.module("app", []);
app.controller('AppController', ['$scope', function ($scope) {
var vm = this;
vm.testNumber = 10;
}]);
app.directive('numericOnly', function () {
return {
require: 'ngModel',
link: function (scope, element, attrs, modelCtrl) {
modelCtrl.$parsers.push(function (inputValue) {
if (angular.isNumber(inputValue)) {
return inputValue;
}
var transformedInput = inputValue ? Number(inputValue.replace(/[^\d.-]/g, '')) : null;
if (transformedInput != inputValue) {
modelCtrl.$setViewValue(transformedInput);
modelCtrl.$render();
}
return transformedInput;
});
}
};
});
app.directive('numberSpin', [function () {
return {
restrict: 'E',
scope: {
"ngModel": '='
},
template: '<div>' +
'<input numeric-only data-ng-model="ngModel" ng-pattern="onlyNumbers" type="text">' +
'<a class="ns-plus" data-ng-click="plus()">+</a>' +
'<a class="ns-minus"data-ng-click="minus()">-</a> </div>',
link: function (scope, elem, attrs) {
scope.onlyNumbers = /^\d+$/;
scope.plus = function () {
scope.ngModel = scope.ngModel + 1;
};
scope.minus = function () {
scope.ngModel = scope.ngModel - 1;
};
}
}
}])
}());
number-spin div {
position: relative;
width: 126px;
}
number-spin input {
height: 32px;
width: 100%;
text-align: right;
padding-right: 20px;
box-sizing: border-box;
font-size: 16px;
}
number-spin .ns-plus {
position: absolute;
text-align: center;
line-height: 16px;
top: 0;
right: 0;
height: 16px;
display: block;
border-left: 1px solid #ccc;
border-bottom: 1px solid #ccc;
width: 16px;
}
number-spin .ns-minus {
position: absolute;
text-align: center;
display: block;
line-height: 16px;
height: 16px;
border-left: 1px solid #ccc;
bottom: 0;
right: 0;
width: 16px;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.2/angular.min.js"></script>
<div ng-app="app" style="padding: 16px; "data-ng-controller="AppController as vm">
<number-spin data-ng-model="vm.testNumber"></number-spin>
</div>
更新: 允许将 min
/max
传递到指令中的更简单的代码:
(function () {
"use strict";
var app = angular
.module("app", []);
app.controller('AppController', ['$scope', function ($scope) {
var vm = this;
vm.testNumber = 10;
}]);
app.directive('numberSpin', [function () {
return {
restrict: 'E',
scope: {
"ngModel": '=',
"min": '<',
"max": '<',
"step": '<'
},
template: '<div>' +
'<input data-ng-model="ngModel" type="number" ng-attr-min="{{min}}" ng-attr-max="{{max}}">' +
'<a class="btn ns-plus" data-ng-click="plus()">+</a>' +
'<a class="btn ns-minus"data-ng-click="minus()">-</a> </div>',
link: function (scope, elem, attrs) {
scope.plus = function () {
if (scope.ngModel >= scope.max) return;
scope.ngModel += (scope.step || 1);
checkModel()
};
scope.minus = function () {
if (scope.ngModel <= scope.min) return;
scope.ngModel -= (scope.step || 1);
checkModel();
};
function checkModel() {
if (!scope.ngModel) scope.ngModel = scope.min || 0;
}
}
}
}])
}());
number-spin div {
position: relative;
width: 126px;
}
number-spin input {
height: 32px;
width: 100%;
text-align: right;
padding-right: 20px;
box-sizing: border-box;
font-size: 16px;
}
number-spin .btn {
position: absolute;
text-align: center;
line-height: 16px;
display: block;
height: 16px;
right: 0;
border-left: 1px solid #ccc;
width: 16px;
cursor: pointer;
user-select: none;
}
number-spin .ns-plus {
top: 0;
border-bottom: 1px solid #ccc;
cursor: pointer;
user-select: none;
}
number-spin .ns-minus {
bottom: 0;
}
number-spin input[type=number]::-webkit-inner-spin-button,
number-spin input[type=number]::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.2/angular.min.js"></script>
<div ng-app="app" style="padding: 16px; "data-ng-controller="AppController as vm">
<number-spin data-ng-model="vm.testNumber" min="0" max="15"></number-spin>
</div>
(function () {
"use strict";
var app = angular.module("app", ['tien.stepInput']);
app.controller('AppController', function ($scope) {
$scope.demo = 10
$scope.options = {
min_value: 1,
overrides: [
{value: 1, style: 'danger', view_value: '<i class="fa fa-times"></i>'},
{value: 0, style: 'warning', view_value: '<i class="fa fa-question"></i>'}
]
};
});
}());
.tien-step {
display: inline-block;
height: 24px;
width: 93px; }
.tien-step button, .tien-step .step-value {
border: none;
float: left;
height: 24px;
text-align: center; }
.tien-step button:focus, .tien-step button:active, .tien-step button:focus:active, .tien-step .step-value:focus, .tien-step .step-value:active, .tien-step .step-value:focus:active {
outline: none; }
.tien-step button {
background: transparent;
color: white;
line-height: 24px;
width: 24px; }
.tien-step .step-value {
border-bottom: 1px solid transparent;
border-top: 1px solid transparent;
font-size: 18px;
line-heigth: 22px;
padding: 0;
width: 45px; }
.tien-step.primary button {
background: #428bca; }
.tien-step.primary button:active {
background: #3071a9; }
.tien-step.primary button.disabled {
opacity: 0.8; }
.tien-step.primary button.disabled:active {
background: #428bca; }
.tien-step.primary .step-value {
border-color: #428bca; }
.tien-step.primary .step-value i.fa {
color: #428bca;
font-size: 14px;
line-height: 20px;
top: -2px;
position: relative; }
.tien-step.success button {
background: #5cb85c; }
.tien-step.success button:active {
background: #449d44; }
.tien-step.success button.disabled {
opacity: 0.8; }
.tien-step.success button.disabled:active {
background: #5cb85c; }
.tien-step.success .step-value {
border-color: #5cb85c; }
.tien-step.success .step-value i.fa {
color: #5cb85c;
font-size: 14px;
line-height: 20px;
top: -2px;
position: relative; }
.tien-step.info button {
background: #5bc0de; }
.tien-step.info button:active {
background: #31b0d5; }
.tien-step.info button.disabled {
opacity: 0.8; }
.tien-step.info button.disabled:active {
background: #5bc0de; }
.tien-step.info .step-value {
border-color: #5bc0de; }
.tien-step.info .step-value i.fa {
color: #5bc0de;
font-size: 14px;
line-height: 20px;
top: -2px;
position: relative; }
.tien-step.warning button {
background: #f0ad4e; }
.tien-step.warning button:active {
background: #ec971f; }
.tien-step.warning button.disabled {
opacity: 0.8; }
.tien-step.warning button.disabled:active {
background: #f0ad4e; }
.tien-step.warning .step-value {
border-color: #f0ad4e; }
.tien-step.warning .step-value i.fa {
color: #f0ad4e;
font-size: 14px;
line-height: 20px;
top: -2px;
position: relative; }
.tien-step.danger button {
background: #d9534f; }
.tien-step.danger button:active {
background: #c9302c; }
.tien-step.danger button.disabled {
opacity: 0.8; }
.tien-step.danger button.disabled:active {
background: #d9534f; }
.tien-step.danger .step-value {
border-color: #d9534f; }
.tien-step.danger .step-value i.fa {
color: #d9534f;
font-size: 14px;
line-height: 20px;
top: -2px;
position: relative; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.22/angular.min.js"></script>
<script src="http://angular-step-input.10kb.nl/angular-step-input.min.js"></script>
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet">
<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.1.0/css/font-awesome.min.css" rel="stylesheet">
<div ng-app="app" ng-controller="AppController">
<tien-step-input ng-model="demo"></tien-input-step>
</div>