ngOptionsディレクティブを使ってselect要素を作成する際に初期値(selected)を設定しようとしてハマったのでメモ。バージョンが1.3.15→1.4.0になって変わった点も気づいたので、その補足も合わせてメモメモ。
コントローラー側からデフォルト値(selected)を設定する
コントローラー側で定義したJSON形式のデータを受け取り、ngOptionsディレクティブでselect要素を作成します。html側は以下の通り。AngularJSはとりあえず、version 1.3.15 を読み込みます。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>ngOptions</title>
</head>
<body ng-controller="myController">
<select ng-model="personModel" ng-options="person.id as person.name for person in personList"></select>
<p ng-bind="personModel"></p>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<script src="demo.js"></script>
</body>
</html>
htmlで読み込んでいるdemo.jsは以下の通り。
(function (angular, document) {
"use strict";
var
app = angular.module("myApp", []);
app.controller("myController", ["$scope", function ($scope) {
$scope.personList = [
{"id": 1, "name": "鈴木"},
{"id": 2, "name": "山田"},
{"id": 3, "name": "佐藤"}
];
}]);
angular.bootstrap(document, ["myApp"], {"strictDi": true});
}(angular, document));
このまま実行するとselect要素が以下のように表示されます。
<select ng-model="personModel" ng-options="person.id as person.name for person in personList" class="ng-pristine ng-untouched ng-valid">
<option value="?" selected="selected" label=""></option>
<option value="0" label="鈴木">鈴木</option>
<option value="1" label="山田">山田</option>
<option value="2" label="佐藤">佐藤</option>
</select>
select要素が出来ました。......が、option要素に謎の要素が出来上がってます。これは、出来上がった要素とselect要素(モデル)のbindが出来ていないために(選択されていない)自動的に出来上がってしまうようです。ですので、どれかしらのoption要素をデフォルトで選択状態にします。今回は2番目の要素の{"id":2,"name":"山田"}のデータを選択状態にします。
コントローラーでデフォルト選択値を指定します。
(function (angular, document) {
"use strict";
var
app = angular.module("myApp", []);
app.controller("myController", ["$scope", function ($scope) {
$scope.personList = [
{"id": 1, "name": "鈴木"},
{"id": 2, "name": "山田"},
{"id": 3, "name": "佐藤"}
];
// デフォルト値を設定します。select要素のモデル名=配列のvalue属性
$scope.personModel = $scope.personList[1].id;
}]);
angular.bootstrap(document, ["myApp"], {"strictDi": true});
}(angular, document));
これで、最初に「山田」が選択された状態で、謎のoption要素も表示されなくなりました。
......で問題はここから。
同じ配列から複数行にselect要素を作成したい場合のデフォルト値設定
その行毎のselect要素に直接デフォルト値を設定するところに行き着きました。調べたところ、以下の方法でいけるようです。
<!-- ng-init="モデル名=値"で設定 -->
<select ng-model="personModel1" ng-options="person.id as person.name for person in personList" ng-init="personModel1=2"></select>
<select ng-model="personModel2" ng-options="person.id as person.name for person in personList" ng-init="personModel2=3"></select>
\(^o^)/で・き・た!
わかりづらいと思った点
Chromeのデベロッパーツールで見るとわかるのですが、option要素のvalue属性は0から連番で振られています。「ん?」と思ったのですが、ng-bind="personMode"で確認したらちゃんとバインドされていて「山田」を選択したら「2」とIDの値を表示してくれました。
これがわかりやすくなったのが、1.4系。AngularJSを1.4系に変更して表示すると、以下のように表示されます。
<select ng-model="personModel" ng-options="person.id as person.name for person in personList" class="ng-pristine ng-untouched ng-valid">
<option value="0" label="鈴木">鈴木</option>
<option value="1" label="山田" selected="selected">山田</option>
<option value="2" label="佐藤">佐藤</option>
</select>
<select ng-model="personModel" ng-options="person.id as person.name for person in personList" ng-init="personModel=2" class="ng-pristine ng-untouched ng-valid">
<option value="number:1" label="鈴木">鈴木</option>
<option value="number:2" label="山田" selected="selected">山田</option>
<option value="number:3" label="佐藤">佐藤</option>
</select>
そう、value="idの型:idの値" で表示されます!おぉ〜すごい!
ハマった件
1.4系にしたことにより、ようやく気づいたのが今回。
1.3系で初期値を設定していた時に、
<select mg-model="personModel" ng-init="personModel=2" ...
このように設定しているにもかかわらず、デフォルト値が設定されませんでした。
なんでー!ってなってまして、ふと先日1.4系がリリースされたのでライブラリを変更しました。すると、上記でも述べた通り value="idの型:idの値" で表示されるようになって、
( ゚д゚) ハッ!
<select ng-model="personModel" ng-options="person.id as person.name for person in personList" ng-init="personModel=2" class="ng-pristine ng-untouched ng-valid">
<option value="string:1" label="鈴木">鈴木</option>
<option value="string:2" label="山田" selected="selected">山田</option>
<option value="string:3" label="佐藤">佐藤</option>
</select>
文字列!
コントローラーのJSONデータを確認
$scope.personList = [
{"id": "1", "name": "鈴木"},
{"id": "2", "name": "山田"},
{"id": "3", "name": "佐藤"}
];
うわあああああああ!なんて愚かなんだろ......
ng-initの記述を以下のとおりにすれば問題なくデフォルト値が設定されました。つらい。
<select mg-model="personModel" ng-init="personModel='2'" ...
/(^o^)\ナンテコッタイ
けど、1.4系になってちょこちょこ変わってるなぁ。2系はまた全然違うみたいだしそれはそれで楽しみ。