web-dev-qa-db-ja.com

モデルに数値を使用するAngularjs ng-optionsは初期値を選択しません

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 があります。これは、問題と、私がとったが満足していない他のアプローチを示しています。

この例では、選択オプションは「mV」ではなく、空の値で初期化されています。別のオプションを選択した場合、バインディングは正常に機能するようです-selectedUnitOrdinalは適切に更新されます。

初期モデル値を数値ではなく文字列に設定すると、初期選択が機能することに気付きました(フィドルの#3を参照)。

Ng-optionsが数値オプション値でNiceを再生することを本当に望んでいます。これをエレガントに達成するにはどうすればよいですか?

59
BrandonLWhite

ng-selectディレクティブに関するAngularのドキュメントは、この問題を解決する方法を説明しています。 https://code.angularjs.org/1.4.7/docs/api/ng/directive/select (最後のセクション)を参照してください。

convert-to-numberディレクティブを作成して、選択タグに適用できます。

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>

注:ドキュメントのディレクティブがnullを処理しないことがわかったため、少し調整する必要がありました。

100
Christophe L

少し面倒かもしれませんが、ng-optionsで特別な機能を使用しなくても結果を得ることができます

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

Unit.idを取得すると、整数ではなく文字列が返されるためです。 JavaScriptのオブジェクトは、キーを文字列として保存します。したがって、それを行う唯一の方法は、引用によって4を囲むアプローチです。

編集

<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);
};
16
Mathew Berg

フィルタ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);
        };
    }]);
9
zooblin

クリストフの安否を追加するために:それを達成し維持する最も簡単な方法は、指令を作成することです:

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

クリストフの回答は、「val?」でfalseを返すため、「0」では正しく機能しません。テスト。

8
s3r3k

他の解決策は、単に整数として値を確立するために非常に複雑だと思います。私は使うだろう:

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

Angularはidプロパティを文字列として表示し、引用符を追加します。

self.selectedUnitOrdinal = "4";
3
tymeJV

TymeJVの答えと非常によく似ていますが、簡単な回避策は、デフォルトの選択番号を次のような文字列に変換することです。

self.selectedUnitOrdinal = valueThatCameFromServer.toString();

この方法では、数値をハードコーディングする必要はなく、受け取った値を変換するだけです。フィルターやディレクティブがなくても簡単に修正できます。

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

UnitsOptionsのidプロパティを数値として作成します

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

http://jsfiddle.net/htwc10nx/

1
oadcub

Mathew Bergが提供するソリューションは機能しますが、スティング値の選択オプションを使用する他の選択を中断する可能性があります。 selectを処理するための1つの汎用ディレクティブを作成しようとすると、これが問題になる可能性があります(私がしたように)。

良い回避策は、値が数値であるかどうか(数値を含む文字列であっても)を確認し、次のように変換することです。

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;
};
0
bwitkowicz