Двусторонняя привязка с диапазоном и номером ввода в AngularJS
Я только начинаю играть с AngularJS и пытаюсь понять технику привязки. Для начала я попытался сделать простой калькулятор конверсии (десятки штук, штук до десятков). Это сработало хорошо, но когда я попытался связать как вход диапазон, так и вход число для того же свойства модели, вход номер не обновляется когда значение диапазон настроено. У меня есть jsfiddle, показывающий поведение:
общий javascript для сломанных и работающих скриптов:
var myApp = angular.module('myApp', []);
myApp.controller('CalcCtrl', function ($scope) {
var num = 0.0;
$scope.qty = new Quantity(12);
$scope.num = num;
});
function Quantity(numOfPcs) {
var qty = numOfPcs;
var dozens = numOfPcs / 12;
this.__defineGetter__("qty", function () {
return qty;
});
this.__defineSetter__("qty", function (val) {
qty = val;
dozens = val / 12;
});
this.__defineGetter__("dozens", function () {
return dozens;
});
this.__defineSetter__("dozens", function (val) {
dozens = val;
qty = val * 12;
});
}
BROKEN FIDDLE
HTML:
<div ng-controller="CalcCtrl">
<form>
<label for="pcs">Pieces:</label>
<input type="number" min="0" ng-model="qty.qty" size="20" id="pcs"
/>
<input type="range" min="0" max="100" ng-model="qty.qty" />
<br/>
<label for="numOfDozens">Dozens</label>
<input type="number" min="0" ng-model="qty.dozens" size="20"
id="numOfDozens" />
</form>
</div>
Однако привязка двух число входов к одному и тому же свойству модели, кажется, работает нормально, как показано в этой скрипте:
РАБОЧИЙ FIDDLE
HTML:
<div ng-controller="CalcCtrl">
<form>
<label for="pcs">Pieces:</label>
<input type="number" min="0" ng-model="qty.qty" size="20" id="pcs"
/>
<input type="number" min="0" max="100" ng-model="qty.qty" />
<br/>
<label for="numOfDozens">Dozens</label>
<input type="number" min="0" ng-model="qty.dozens" size="20"
id="numOfDozens" />
</form>
</div>
Любые идеи о том, как получить диапазон и число, связанный с единственным свойством модели в AngularJS? Спасибо.
Ответы
Ответ 1
Проблема заключается в том, что тип ввода = "диапазон" работает с Строками, а не с Числами (в то время как тип ввода = "число" работает только с Числами).
http://www.w3.org/wiki/HTML/Elements/input/range
Состояние диапазона представляет собой элемент управления для установки значения элемента для строка, представляющая число.
Если вы добавите val = parseInt(val)
в качестве первой инструкции в установщик qty
, он должен работать:
this.__defineSetter__("qty", function (val) {
val = parseInt(val);
qty = val;
dozens = val / 12;
});
jsfiddle: http://jsfiddle.net/bmleite/2Pk3M/2/
Ответ 2
Я думаю, что это решение более общее.
myApp.directive('input', function() {
return {
restrict: 'E',
require: '?ngModel',
link: function(scope, element, attrs, ngModel) {
if ('type' in attrs && attrs.type.toLowerCase() === 'range') {
ngModel.$parsers.push(parseFloat);
}
}
};
});
полное объяснение
Ответ 3
Вы можете решить эту проблему, используя ng-model-options
. Я изменил jsfiddle и вот код:
HTML
<div ng-controller="CalcCtrl">
<form>
<label for="pcs">Pieces:</label>
<input type="number" min="0" ng-model="qty.qty" size="20" id="pcs" ng-model-options="{ getterSetter: true }"/>
<input type="range" min="0" max="100" ng-model="qty.qty" ng-model-options="{ getterSetter: true }"/>
<br/>
<label for="numOfDozens">Dozens</label>
<input type="number" min="0" ng-model="qty.dozens" size="20"
id="numOfDozens" ng-model-options="{ getterSetter: true }"/>
</form>
</div>
JS
var myApp = angular.module('myApp', []);
myApp.controller('CalcCtrl', function ($scope) {
var num = 1.0;
$scope.qty = {
qty:function (val) {
return arguments.length ? (num = parseFloat(val)) : num;
},
dozens: function (val) {
return arguments.length ? (num = val*12) : num/12;
}
};
});