2015-01-23 11 views
53

Ich versuche, ng-Optionen mit einem <select> zu verwenden, um einen numerischen ganzzahligen Wert an eine Liste der entsprechenden Optionen zu binden. In meinem Controller habe ich so etwas wie dieses:Angularjs ng-Optionen mit der Nummer für das Modell wählt nicht den Anfangswert

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> 

Und hier ist ein jsFiddle das Problem demonstriert und einige andere Ansätze, die ich habe getroffen, aber bin nicht glücklich mit.

Die Auswahloption wird mit einem leeren Wert anstelle von "mV" initialisiert, wie in diesem Beispiel erwartet. Die Bindung scheint gut zu funktionieren, wenn Sie eine andere Option auswählen - ausgewählte UnitsOrdinal Updates ordnungsgemäß.

Ich habe festgestellt, dass wenn Sie den ursprünglichen Modellwert auf eine Zeichenfolge anstelle einer Zahl festlegen, dann funktioniert die anfängliche Auswahl (siehe # 3 in der Geige).

Ich möchte wirklich ng-Optionen mit numerischen Option Werte schön zu spielen. Wie kann ich das elegant erreichen?

Antwort

82

Angulas Dokumentation für die Richtlinie ng-select erklärt, wie dieses Problem gelöst werden kann. Siehe https://code.angularjs.org/1.4.7/docs/api/ng/directive/select (letzter Abschnitt).

Sie können eine convert-to-number Richtlinie erstellen und anwenden, um sie Ihren Tag select:

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> 

Hinweis: Ich fand die Richtlinie aus dem Doc behandelt Nullen nicht, also musste ich es ein wenig zwicken.

+2

die meiste Zeit wäre * convert-to-string *, ändern Sie einfach * parseInt * in * String * –

+0

Dies sollte die akzeptierte Antwort sein, da sie allgemeiner ist und nicht von 'ng-Optionen' abhängt. Beachten Sie auch, dass dies nicht für eine Zahl, sondern nur für Ganzzahlen gilt. Wenn Floats funktionieren sollen, verwenden Sie 'parseFloat()', aber wenn Sie Floats für Gleichheit vergleichen, tun Sie wahrscheinlich etwas sehr, sehr falsches. –

+2

Schöne Lösung. Aber wenn Sie 0 in Ihren Auswahloptionen haben, gibt es null wegen der Implementierung. Für diesen Fall ist eine kleine Optimierung erforderlich. – user1776573

14

Es ist, weil wenn Sie die unit.id erhalten, es eine Zeichenfolge nicht eine ganze Zahl zurückgibt. Objekte in Javascript speichern ihre Schlüssel als Zeichenfolgen. Der einzige Weg, dies zu tun, ist Ihr Ansatz, 4 nach Zitaten zu umschließen.

bearbeiten

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

Danke. Ich bekomme einen numerischen Wert vom Server, und ich muss einen numerischen Wert zurücksenden. Es gibt eine Menge davon. Ich möchte wirklich vermeiden, Conversion-Code in den Controller zu schreiben. (Es scheint, als hätte ich diesen Knockout nie gehabt). Was ist ein kluger/fauler Weg, den ich bekommen kann, was ich will? – BrandonLWhite

+0

Angular ist restriktiver als Knockout in diesem Aspekt, denke ich :). Wie auch immer ich die Frage bearbeitet habe, um Ihnen eine Option zu zeigen, die Sie tun können. –

+0

Ok, damit kann ich fast leben. – BrandonLWhite

3

Angular ist Ihre id Eigenschaft als String zu sehen, fügen Sie Zitate:

self.selectedUnitOrdinal = "4"; 
9

Sie können auch Filter definieren number, wird dieser Filter automatisch String-Wert analysieren 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); 
     }; 
    }]); 
+2

Sie sollten immer ein Radix verwenden, wenn Sie 'parseInt' verwenden, wie folgt:' return parseInt (input, 10); ' – doug65536

0

Während die von Mathew Berg gelieferte Lösung funktioniert, wird sie wahrscheinlich andere Selects brechen, die sting-bewertete Auswahloptionen verwenden. Dies kann ein Problem sein, wenn Sie versuchen, eine universelle Direktive für die Behandlung von Selektionen zu schreiben (wie ich es tat).

Eine nette Abhilfe ist, zu überprüfen, ob der Wert eine Zahl ist (auch wenn es sich um eine Zeichenfolge, die eine Zahl enthalten), und nur als die Umwandlung zu tun, etwa so:

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

oder als eine Controller-Methode:

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

Nur Christophes answear hinzuzufügen: einfachste Weg, um zu achive und maintaint es eine Richtlinie zu machen ist:

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

Christophes answear nicht funktionieren richtig für '0', da sie den Wert false zurück auf "val?" Prüfung.

31

Vielleicht ist es ein bisschen chaotisch, aber Ergebnis ohne Sonderfunktionen direkt in ng-Optionen erreicht wird

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

Es ist wirklich die einfachste Antwort. Die angularJS-Bibliothek Version 1.3.10 verwendet in der [jsFiddle] (http://jsfiddle.net/LatencyMachine/x75t70pd) hatte einen Fehler und + unit.id Notation hat nicht funktioniert, aber es tut ab 1.4.0; siehe [work jsFiddle] (http://jsfiddle.net/x75t70pd/4/) – cnlevy

+0

Die angenommene Antwort funktionierte nicht in Kombination, wenn die select-Klausel in ng-otpions verwendet wurde. Das hat aber funktioniert. –

+3

aber der Wert der Option ist: Wert = "Nummer: 0", mit "Nummer" – YETI

2

Sehr ähnlich tymeJV Antwort, einfache Abhilfe ist die Standardauswahl Zahl in einen String wie diese konvertieren :

Auf diese Weise müssen Sie die Nummer nicht fest codieren, Sie können nur jeden empfangenen Wert konvertieren. Es ist eine einfache Lösung ohne Filter oder Direktiven.

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

Dies liefert keine Antwort auf die Frage. Um einen Autor zu kritisieren oder um Klärung zu bitten, hinterlasse einen Kommentar unter seinem Beitrag. - [Aus Bewertung] (/ review/low-quality-posts/18363212) – Mamun

+0

Während dieses Code-Snippet die Lösung sein kann, hilft eine Erklärung, um die Qualität Ihres Posts zu verbessern. Denken Sie daran, dass Sie die Frage für Leser in der Zukunft beantworten, und diese Leute könnten die Gründe für Ihren Codevorschlag nicht kennen –