angularjs ng-options angularjs-ng-options

Las opciones ng de Angularjs que usan el número para el modelo no seleccionan el valor inicial



ng-options angularjs-ng-options (11)

Angular está viendo su propiedad de id como una cadena, agregue comillas:

self.selectedUnitOrdinal = "4";

Estoy tratando de usar ng-options con un <select> para vincular un valor entero numérico a una lista de opciones correspondientes. En mi controlador, tengo algo como esto:

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>

Y aquí hay un jsFiddle demuestra el problema, y ​​algunos otros enfoques que he adoptado pero con los que no estoy satisfecho.

La opción de selección se inicializa con un valor vacío, en lugar de "mV" como se esperaba en este ejemplo. El enlace parece funcionar bien si selecciona una opción diferente: selectedUnitOrdinal se actualiza correctamente.

Me di cuenta de que si establece el valor del modelo inicial en una cadena en lugar de un número, entonces la selección inicial funciona (consulte el n. ° 3 en el violín).

Realmente me gustaría que ng-options juegue bien con los valores numéricos de las opciones. ¿Cómo puedo lograr esto con elegancia?


Creo que las otras soluciones son demasiado complejas para simplemente establecer el valor como un número entero. Yo usaría:

<select ng-model="model.id"> <option ng-value="{{ 0 }}">Zero</option> <option ng-value="{{ 1 }}">One</option> <option ng-value="{{ 2 }}">Two</option> </select>


De manera muy similar a la respuesta de tymeJV, la solución simple es convertir el número de selección predeterminado en una cadena como esta:

self.selectedUnitOrdinal = valueThatCameFromServer.toString();

De esta manera, no tiene que codificar el número, simplemente puede convertir cualquier valor recibido. Es una solución fácil sin filtros ni directivas.


Es porque cuando obtienes unit.id está devolviendo una cadena, no un entero. Los objetos en JavaScript almacenan sus claves como cadenas. Entonces, la única forma de hacerlo es mediante el enfoque de rodear 4 entre comillas.

Editar

<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); };


Hacer propiedad de identificación en unidades Opciones como número

self.unitsOptions = Object.keys(unitOptionsFromServer).map(function (key) { return { id: +key, text: unitOptionsFromServer[key] }; });

http://jsfiddle.net/htwc10nx/


La documentación de Angular para la directiva ng-select explica cómo resolver este problema. Ver https://code.angularjs.org/1.4.7/docs/api/ng/directive/select (última sección).

Puede crear una directiva de convert-to-number y aplicarla a su etiqueta de selección:

JS :

module.directive(''convertToNumber'', function() { return { require: ''ngModel'', link: function(scope, element, attrs, ngModel) { ngModel.$parsers.push(function(val) { return val != null ? parseInt(val, 10) : null; }); ngModel.$formatters.push(function(val) { return val != null ? '''' + val : null; }); } }; });

HTML :

<select ng-model="model.id" convert-to-number> <option value="0">Zero</option> <option value="1">One</option> <option value="2">Two</option> </select>

Nota: descubrí que la directiva del documento no maneja los valores nulos, así que tuve que modificarla un poco.


Si bien la solución provista por Mathew Berg funciona, probablemente romperá otras selecciones que usan opciones de selección con valor de picadura. Esto puede ser un problema si intenta escribir una directiva universal para manejar selecciones (como lo hice).

Una buena solución es verificar si el valor es un número (incluso si es una cadena que contiene un número) y solo hacer la conversión, así:

angular.module(''<module name>'').filter(''intToString'', [function() { return function(key) { return (!isNaN(key)) ? parseInt(key) : key; }; }]);

o como un método de controlador:

$scope.intToString = function(key) { return (!isNaN(key)) ? parseInt(key) : key; };


Solo para agregar la ropa de Christophe: la forma más fácil de lograr y mantener es hacer una directiva:

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 ; }); } }; });

La answear de Christophe no funcionará correctamente para ''0'' ya que devuelve falso en "val?" prueba.


Tal vez sea un poco complicado, pero el resultado se puede lograr sin funciones especiales directamente en ng-options

<select ng-model="ctrl.selectedUnitOrdinal" ng-options="+(unit.id) as unit.text for unit in ctrl.unitsOptions"></select>


También puede definir el number filtro, este filtro analizará automáticamente el valor de cadena a 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); }; }]);


<select ng-model="ctrl.selectedUnitOrdinal" ng-options="+(unit.id) as unit.text for unit in ctrl.unitsOptions"></select>