Angularjs ng-параметры, использующие число для модели, не выбирают начальное значение
Я пытаюсь использовать ng-options с <select> для привязки числового целого значения к списку соответствующих параметров. В моем контроллере, у меня есть что-то вроде этого:
myApp.controller('MyCtrl', function() {
var self = this;
var unitOptionsFromServer = {
2: "mA",
3: "A",
4: "mV",
5: "V",
6: "W",
7: "kW"
};
self.unitsOptions = Object.keys(unitOptionsFromServer).map(function (key) {
return { id: key, text: unitOptionsFromServer[key] };
});
self.selectedUnitOrdinal = 4; // Assume this value came from the server.
});
HTML:
<div ng-controller="MyCtrl as ctrl">
<div>selectedUnitOrdinal: {{ctrl.selectedUnitOrdinal}}</div>
<select ng-model="ctrl.selectedUnitOrdinal" ng-options="unit.id as unit.text for unit in ctrl.unitsOptions"></select>
</div>
и вот это jsFiddle демонстрируя проблему, и некоторые другие подходы, которые я принял, но не доволен.
опция select инициализируется пустым значением, а не "mV", как ожидалось в этом примере. Привязка кажется чтобы работать нормально, если вы выберете другой параметр -- selectedUnitOrdinal обновления правильно.
Я заметил, что если вы установите начальное значение модели в строку вместо числа, то первоначальный выбор работает (см. #3 в скрипке).
Я действительно хотел бы, чтобы ng-options играли хорошо с числовыми значениями опций. Как я могу достичь этого элегантно?
9 ответов:
может быть, это немного грязно, но результат может быть достигнут без специальных функций прямо в NG-options
<select ng-model="ctrl.selectedUnitOrdinal" ng-options="+(unit.id) as unit.text for unit in ctrl.unitsOptions"></select>
это потому, что когда вы получаете unit.id он возвращает строку, а не целое число. Объекты в javascript хранят свои ключи в виде строк. Таким образом, единственный способ сделать это-ваш подход к окружению 4 цитатами.
Edit
<select ng-model="ctrl.selectedUnitOrdinal" ng-options="convertToInt(unit.id) as unit.text for unit in ctrl.unitsOptions"></select> $scope.convertToInt = function(id){ return parseInt(id, 10); };
вы также можете определить фильтр
number, этот фильтр будет автоматически анализировать строковое значение int:<select ng-model="ctrl.selectedUnitOrdinal" ng-options="unit.id|number as unit.text for unit in ctrl.unitsOptions"></select> angular.module('filters').filter('number', [function() { return function(input) { return parseInt(input, 10); }; }]);
просто добавить answear Кристофа: самый простой способ достичь и поддерживать его - сделать директиву:
JS:
.directive('convertToNumber', function() { return { require: 'ngModel', link: function(scope, element, attrs, ngModel) { ngModel.$parsers.push(function(val) { //saves integer to model null as null return val == null ? null : parseInt(val, 10); }); ngModel.$formatters.push(function(val) { //return string for formatter and null as null return val == null ? null : '' + val ; }); } }; });answear Кристофа не будет работать правильно Для '0', поскольку он возвращает false на " val?" испытание.
очень похоже на ответ tymeJV, простым обходным путем является преобразование номера выбора по умолчанию в строку следующим образом:
self.selectedUnitOrdinal = valueThatCameFromServer.toString();таким образом, вам не нужно жестко кодировать число, вы можете просто преобразовать любое полученное значение. Это легко исправить без каких-либо фильтров или директив.
в то время как решение, предоставленное Mathew Berg works, вероятно, сломает другие варианты выбора, которые используют параметры выбора sting-valued. Это может быть проблемой, если вы попытаетесь написать одну универсальную директиву для обработки выбирает (как я сделал).
хороший обходной путь-проверить, является ли значение числом (даже если это строка, содержащая число) и только чем сделать преобразование, например:
angular.module('<module name>').filter('intToString', [function() { return function(key) { return (!isNaN(key)) ? parseInt(key) : key; }; }]);или как метод контроллера:
$scope.intToString = function(key) { return (!isNaN(key)) ? parseInt(key) : key; };
<select ng-model="ctrl.selectedUnitOrdinal" ng-options="+(unit.id) as unit.text for unit in ctrl.unitsOptions"></select>
Comments