39

This is my angular html file code. In my mongo database frequencyType added as frequencyType = "1", but I want frequencyType = NumberInt(1);

<div class="span4">
  <select class="span12 combobox" ng-model="frequencyType" required>
    <option value="1">Daily</option>
    <option value="2">Weekly</option>
    <option value="3">Monthly</option>
    <option value="4">Yearly</option>
  </select>
</div>

I get in my database frequencyType = "1" but I want frequencyType = NumberInt(1).

peterh
  • 11,875
  • 18
  • 85
  • 108
Nishchit
  • 18,284
  • 12
  • 54
  • 81
  • 5
    Please reconsider your selected answer as it is only partially correct. As Trak mentioned in his answer the _accepted_ answer doesn't work for situations where his answer **does** work. When another person like me comes along I'd rather see the "most correct" answer selected. Luckily, I don't take anything at face value or else I'd have found out the hard way the "answer" would not have worked for me. :) – Tim Hobbs Dec 02 '14 at 00:28

6 Answers6

61

There is an easier way:

Just use value*1 as your id, that will convert the string to int without changing the value... assuming the id is an integer.

so the result is>

<div ng-app ng-controller="MyCtrl">
    <select ng-model="selectedItem" ng-options="selectedItem*1 as selectedItem for selectedItem in values"></select>
    selectedItem: {{selectedItem}}
</div>

This will work in more cases, since indexOf is not available in objects, only in arrays. This solution works for objects with integers as keys (for example if some keys are missing, or if you use db ids)

Trak
  • 677
  • 1
  • 5
  • 7
  • But what if it's not an integer? Generally, assumptions are bad ;-) – Tim Apr 25 '14 at 19:26
  • 4
    The question asks about keys as integers, if it's not an integer, and it is a string, then more assumptions are being made, since you're trusting the order of the datasource – Trak Apr 25 '14 at 19:30
  • Better than adding a conversion directive to parse (http://stackoverflow.com/questions/28114970/angularjs-ng-options-using-number-for-model-does-not-select-initial-value) – Lzh May 19 '16 at 15:44
  • I think "+selectedItem" is alittle bit nicer, but it works the same – Michael Filler Apr 03 '17 at 13:20
47

Most solutions discussed here require using the ngOptions directive instead of using static <option> elements in the HTML code, as was the case in the OP's code.

Angular 1.6.x

Edit If you use Angular 1.6.x, just use the ng-value directive and it will work as expected.

angular.module('nonStringSelect', [])
.run(function($rootScope) {
  $rootScope.model = { id: 2 };
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.0/angular.min.js"></script>
<div ng-app="nonStringSelect">
  <select ng-model="model.id">
    <option ng-value="0">Zero</option>
    <option ng-value="1">One</option>
    <option ng-value="2">Two</option>
  </select>
  
  {{ model }}
</div>

Older versions

There is a way to make it work while still using static elements. It's shown in the AngularJS select directive documentation.

The idea is to use a directive to register a parser and a formatter on the model. The parser will do the string-to-int conversion when the item is selected, while the formatter will do the int-to-string conversion when the model changes.

Code below (taken directly from the AngularJS documentation page, credit not mine).

https://code.angularjs.org/1.4.6/docs/api/ng/directive/select#binding-select-to-a-non-string-value-via-ngmodel-parsing-formatting

angular.module('nonStringSelect', [])
.run(function($rootScope) {
  $rootScope.model = { id: 2 };
})
.directive('convertToNumber', function() {
  return {
    require: 'ngModel',
    link: function(scope, element, attrs, ngModel) {
      ngModel.$parsers.push(function(val) {
        return parseInt(val, 10);
      });
      ngModel.$formatters.push(function(val) {
        return '' + val;
      });
    }
  };
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<div ng-app="nonStringSelect">
  <select ng-model="model.id" convert-to-number>
    <option value="0">Zero</option>
    <option value="1">One</option>
    <option value="2">Two</option>
  </select>
  
  {{ model }}
</div>
Philippe Plantier
  • 7,964
  • 3
  • 27
  • 40
33

I've just had the same problem and figured out the right way to do this - no 'magic' required. :)

function MyCtrl($scope) {
    $scope.values = [
        {name : "Daily", id : 1},
        {name : "Weekly", id : 2},
        {name : "Monthly", id : 3},
        {name : "Yearly", id : 4}];
    $scope.selectedItem = $scope.values[0].id;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.2/angular.min.js"></script>
<div ng-app ng-controller="MyCtrl">
    <select ng-model="selectedItem" ng-options="selectedItem.id as selectedItem.name for selectedItem in values"></select>
    selectedItem: {{selectedItem}}
</div>
Andrzej Gis
  • 13,706
  • 14
  • 86
  • 130
12

I think the angular way to do this is to use the directive "convert-to-number" in the select tag.

<select class="span12 combobox" ng-model="frequencyType" required convert-to-number>
    <option value="1">Daily</option>
    <option value="2">Weekly</option>
    <option value="3">Monthly</option>
    <option value="4">Yearly</option>
</select>

You can see the documentation and a fiddle here at the end of the page : https://docs.angularjs.org/api/ng/directive/select

Allenile
  • 300
  • 3
  • 10
11

I suggest you to try to use indexOf.

JS

function MyCtrl($scope) {
    $scope.values = ["Daily","Weekly","Monthly","Yearly"];
    $scope.selectedItem = 0;
}

HTML

<div ng-app ng-controller="MyCtrl">
    <select ng-model="selectedItem" ng-options="values.indexOf(selectedItem) as selectedItem for selectedItem in values"></select>
    selectedItem: {{selectedItem}}
</div>

Demo Fiddle

So send to mongoDB $scope.selectedItem value

Maxim Shoustin
  • 77,483
  • 27
  • 203
  • 225
  • That did help me very much. It seems simple yet took my more than half an hour already :( – Cihad Turhan Apr 17 '14 at 15:42
  • 1
    This doesn't work when your values are specific codes or id's. The solution by Trak below works for all numeric values. – Erwin Jul 15 '14 at 07:51
  • 1
    @Erwin do you want to give an example with my demo? If i'll put `[1,2,3,4,5];` it still works – Maxim Shoustin Jul 15 '14 at 08:09
  • @MaximShoustin I have a list of objects with a value and discription field, with ng-options="code.value as code.discription for code in object.codes" and ng-model="codeField". codeField needs to store the value of the code, which are not equal to the indexes. When I use 'object.codes.indexOf(code)', it stores the index on the field which should get filled with the code. – Erwin Jul 15 '14 at 12:16
  • What if the IDs are [32,12,44,1,900]? This works if selecting by index only. I think this is a good solution for enums that always start from 0 – Lzh May 19 '16 at 15:47
8

This is the easiest way I have found so far:

function Controller($scope) {
    $scope.options = {
        "First option" : 1,
        "Second option" : 2,
        "Last option" : 10
    }
    $scope.myoption = 2;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app ng-controller="Controller">    
    <select ng-model="myoption" ng-options="label for (label, value) in options"></select>
    Option Selected: {{myoption}}
</div>

Or, if you want to use numeric indexes:

function Controller($scope) {
    $scope.options = {
        1 : "First option",
        2 : "Second option",
        10 : "Last option"
    }
    $scope.myoption = 2;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app ng-controller="Controller">    
    <select ng-model="myoption" ng-options="value*1 as label for (value, label) in options"></select>
    Option Selected: {{myoption}}
</div>

For Angular 2, follow the rabit...

Community
  • 1
  • 1
lepe
  • 24,677
  • 9
  • 99
  • 108