Angularjs ng-options using number for model does n

2019-01-08 10:44发布

I'm trying to use ng-options with a <select> to bind a numeric integer value to a list of corresponding options. In my controller, I have something like this:

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>

And here's a jsFiddle demonstrating the problem, and some other approaches I've taken but am not happy with.

The select option is being initialized with an empty value, instead of "mV" as expected in this example. The binding seems to work fine if you select a different option -- selectedUnitOrdinal updates properly.

I've noticed that if you set the initial model value to a string instead of a number, then the initial selection works (see #3 in the fiddle).

I really would like ng-options to play nice with numeric option values. How can I achieve this elegantly?

10条回答
太酷不给撩
2楼-- · 2019-01-08 11:07

I think the other solutions are overly complex for simply establishing the value as an integer. I would use:

<select ng-model="model.id">
    <option ng-value="{{ 0 }}">Zero</option>
    <option ng-value="{{ 1 }}">One</option>
    <option ng-value="{{ 2 }}">Two</option>
</select>
查看更多
放我归山
3楼-- · 2019-01-08 11:09

Angular's documentation for the ng-select directive explains how to solve this problem. See https://code.angularjs.org/1.4.7/docs/api/ng/directive/select (last section).

You can create a convert-to-number directive and apply it to your select tag:

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>

Note: I found the directive from the doc does not handle nulls so I had to tweak it a little.

查看更多
相关推荐>>
4楼-- · 2019-01-08 11:10

Angular is seeing your id property as a string, add quotes:

self.selectedUnitOrdinal = "4";
查看更多
Animai°情兽
5楼-- · 2019-01-08 11:12

Very similarly to tymeJV's answer, simple workaround is to convert the default selection number to a string like this:

self.selectedUnitOrdinal = valueThatCameFromServer.toString();

This way, you don't have to hardcode the number, you can just convert any received value. It's an easy fix without any filters or directives.

查看更多
登录 后发表回答