AngularJSのng-optionsを使用したselectの操作


442

私は他の投稿でそれについて読みましたが、それを理解することができませんでした。

私はアレイを持っています、

$scope.items = [
   {ID: '000001', Title: 'Chicago'},
   {ID: '000002', Title: 'New York'},
   {ID: '000003', Title: 'Washington'},
];

それを次のようにレンダリングしたい:

<select>
  <option value="000001">Chicago</option>
  <option value="000002">New York</option>
  <option value="000003">Washington</option>
</select>

また、ID = 000002のオプションを選択します。

selectを読んで試しましたが、理解できません。


Select2を使用することを強くお勧めします。AngularJSのディレクティブさえあります。
hewstone 2014


実際には、QuantumUIによって開発された純粋なAngularJSソリューションがあります。http://quantumui.org/で他の例やドキュメントを見つけることができます。
Ramon Drunce 2015年

回答:


799

注意すべきことの1つは、ngModelがngOptionsを機能させるために必要であることです。ng-model="blah"これは、「$ scope.blahを選択した値に設定する」と言っていることに注意してください。

これを試して:

<select ng-model="blah" ng-options="item.ID as item.Title for item in items"></select>

AngularJSのドキュメントの詳細を次に示します(まだ見ていなければ)。

配列データソースの場合:

  • 配列の値のラベル
  • 配列の値のラベルとして選択
  • 配列内の値のグループごとにラベルを付ける=配列内の値のグループごとにラベルとして選択

オブジェクトデータソースの場合:

  • オブジェクトの(key、value)のラベル
  • オブジェクトの(key、value)のラベルとして選択
  • オブジェクトの(キー、値)のグループごとにラベルを付ける
  • オブジェクトの(キー、値)のグループごとにグループとしてラベルとして選択

AngularJSのオプションタグの値のいくつかの明確化のため:

を使用する場合ng-optionsng-optionsによって書き出されたオプションタグの値は常に、オプションタグが関連する配列項目のインデックスになります。これは、AngularJSでは、プリミティブ型だけでなく、選択コントロールを使用してオブジェクト全体を実際に選択できるためです。例えば:

app.controller('MainCtrl', function($scope) {
   $scope.items = [
     { id: 1, name: 'foo' },
     { id: 2, name: 'bar' },
     { id: 3, name: 'blah' }
   ];
});
<div ng-controller="MainCtrl">
   <select ng-model="selectedItem" ng-options="item as item.name for item in items"></select>
   <pre>{{selectedItem | json}}</pre>
</div>

上記では、オブジェクト全体を$scope.selectedItem直接選択できます。ポイントは、AngularJSでは、オプションタグの内容を気にする必要がないことです。AngularJSで処理してください。スコープ内のモデルの内容のみを気にする必要があります。

上記の動作を示し、書き出されたHTMLを示すプランカーです


デフォルトオプションの扱い:

デフォルトのオプションに関して、私が上で言及し損ねたことがいくつかあります。

最初のオプションを選択し、空のオプションを削除します。

これを行うにng-initは、モデルを(からng-model)に設定するシンプルな要素を、繰り返しを行うアイテムの最初の要素に追加しますng-options

<select ng-init="foo = foo || items[0]" ng-model="foo" ng-options="item as item.name for item in items"></select>

注:fooたまたま「偽物」に正しく初期化された場合、これは少し気が狂う可能性があります。その場合foo、ほとんどの場合、コントローラーでの初期化を処理する必要があります。

デフォルトオプションのカスタマイズ:

これは少し異なります。ここで必要なのは、selectの子としてoptionタグを追加し、値の属性を空にして、その内部テキストをカスタマイズすることだけです。

<select ng-model="foo" ng-options="item as item.name for item in items">
   <option value="">Nothing selected</option>
</select>

注:この場合、別のオプションを選択した後でも、「空」のオプションが残ります。これは、AngularJSでのselectのデフォルトの動作には当てはまりません。

選択後に非表示になるカスタマイズされたデフォルトオプション:

値を選択した後で、カスタマイズされたデフォルトオプションを削除したい場合は、ng-hide属性をデフォルトオプションに追加できます。

<select ng-model="foo" ng-options="item as item.name for item in items">
   <option value="" ng-if="foo">Select something to remove me.</option>
</select>

3
これらは値のインデックスであることがわかります。これにより、選択ボックスの値としてオブジェクトを使用できるようになります。Angularは、選択ボックスを使用して背後で多くのことを行います。オプションのvalue属性について心配する必要はありません。
Ben Lesh

1
ドキュメントは、サイトの「select」の下にあります:docs.angularjs.org/api/ng.directive
Ben Lesh

25
「... ngOptionsが機能するにはngModelが必要です...」が私にとって問題の核心でした。いい答えです。
Tristanm 2013年

1
最初の空のオプション(<option value="?" selected="selected"></option>)を回避することは可能ですか?
swedo

4
最後のケース(選択した後に非表示になるカスタマイズされたデフォルトオプション)を使用しようとしていますが、いくつかの問題が見つかりました。代わりに、他のオプションが選択されているときにデフォルトの空のオプションを非表示にするためng-if="foo"に使用するng-if=!foo必要がありました。また、デフォルトの空のオプションは、コンボリストの一番下に常に表示されます。コンボリストの先頭に配置するにはどうすればよいですか?
Fran Herrero、

90

私はAngularJSを学んでいて、選択にも苦労していました。この質問はすでに回答済みですが、それでもコードをいくつか共有したいと思います。

私のテストでは、自動車メーカーと自動車モデルの2つのリストボックスがあります。一部のメーカーが選択されるまで、モデルリストは無効になります。メークリストボックスでの選択が後でリセットされる([メイクの選択]に設定される)と、モデルリストボックスは再び無効になり、その選択もリセットされます([モデルの選択]に)。メイクはリソースとして取得されますが、モデルはハードコードされます。

JSONを作成します。

[
{"code": "0", "name": "Select Make"},
{"code": "1", "name": "Acura"},
{"code": "2", "name": "Audi"}
]

services.js:

angular.module('makeServices', ['ngResource']).
factory('Make', function($resource){
    return $resource('makes.json', {}, {
        query: {method:'GET', isArray:true}
    });
});

HTMLファイル:

<div ng:controller="MakeModelCtrl">
  <div>Make</div>
  <select id="makeListBox"
      ng-model="make.selected"
      ng-options="make.code as make.name for make in makes"
      ng-change="makeChanged(make.selected)">
  </select>

  <div>Model</div>
  <select id="modelListBox"
     ng-disabled="makeNotSelected"
     ng-model="model.selected"
     ng-options="model.code as model.name for model in models">
  </select>
</div>

controllers.js:

function MakeModelCtrl($scope)
{
    $scope.makeNotSelected = true;
    $scope.make = {selected: "0"};
    $scope.makes = Make.query({}, function (makes) {
         $scope.make = {selected: makes[0].code};
    });

    $scope.makeChanged = function(selectedMakeCode) {
        $scope.makeNotSelected = !selectedMakeCode;
        if ($scope.makeNotSelected)
        {
            $scope.model = {selected: "0"};
        }
    };

    $scope.models = [
      {code:"0", name:"Select Model"},
      {code:"1", name:"Model1"},
      {code:"2", name:"Model2"}
    ];
    $scope.model = {selected: "0"};
}

27
親愛なるランダムユーザー。この質問とその答えはかなり単純で複雑ではありませんが、適切でそれぞれの場所(コントローラー、サービス、テンプレート、データ)へのコードの編成は、AngularJSの優雅さを最も単純でデフォルトの形式で示しています。素晴らしい例。
Atticus 2013年

1
これは、使用方法ではありません。とは関係なく、スコープ上の別の変数ng-modelを指す必要があります。docs.angularjs.org/api/ng/directive/ngOptionsの例を参照してくださいmake
Dmitri Zaitsev

@DmitriZaitsev私はあなたが間違っていると思います、角度のドキュメントの例があなたが説明した方法を示しているからといって、それが唯一の方法を意味しているわけではありません。初心者のための素晴らしい例をこするのではなく、この方法で使用することを想定していない理由を示してください。
JRT 2015年

39

何らかの理由で、AngularJSは私を混乱させます。彼らのドキュメントはこれに関してかなり恐ろしいです。バリエーションのより良い例を歓迎します。

とにかく、私はベンレッシュの答えに若干のばらつきがあります。

私のデータコレクションは次のようになります。

items =
[
   { key:"AD",value:"Andorra" }
,  { key:"AI",value:"Anguilla" }
,  { key:"AO",value:"Angola" }
 ...etc..
]

さて

<select ng-model="countries" ng-options="item.key as item.value for item in items"></select>

それでもオプションの値はインデックス(0、1、2など)になります。

トラックバイを追加して修正しました:

<select ng-model="blah" ng-options="item.value for item in items track by item.key"></select>

オブジェクトの配列を選択リストに追加したいことがよくあるので、これを覚えておきます!

AngularJS 1.4以降では、ng-optionsを使用できなくなりng-repeatましたが、オプションタグで使用する必要があることに注意してください。

<select name="test">
   <option ng-repeat="item in items" value="{{item.key}}">{{item.value}}</option>
</select>

3
この答えはまさに質問が求めているもののようです。他のすべての答えは、HTMLが生成されることを心配しないように読者に指示しますが、select要素がフォーム内にある場合、私は非常に心配します。正解です。
キース、

3
これにより、キーだけでなく、選択されたオブジェクト全体がモデルに格納されることに注意してください。モデルのキーだけが必要な場合は、「item.key as item.value」バージョンを使用します。これは、モデルで必要なデータではなく、HTMLがどのように表示されるのかを把握するときにしばらく混乱しました。つまり、私にとっては重要なことです。
mhenry1384 2015

@ mhenry1384はい、オブジェクト全体を格納することについては、そうです。IDだけでなく(必要な場合)にアクセスできるため、実際にはこの機能が好きです。リストにmongoコレクションを入力し、選択したアイテムからいくつかのプロパティを取得する必要がある場合は、うまく機能します。
Mattijs、2016

2
そして、内部の "ng-change"で変更をどのように検出できoptionますか?
Konstantinos Natsios 2016年

2
アップデートに関しては、これは正しくありません。ng-optionsは1.5でも正常に動作します。ドキュメントにも表示されます。 docs.angularjs.org/api/ng/directive/select
Jeremy A. West

15

質問はすでに回答されています(BTW、Benによる非常に優れた包括的な回答です)が、完全性のために別の要素を追加したいと思います。これも非常に便利です。

ベンが提案した例では:

<select ng-model="blah" ng-options="item.ID as item.Title for item in items"></select>

次のngOptionsフォームが使用されています:select as label for value in array

ラベルは式であり、結果は<option>要素のラベルになります。その場合、より複雑なオプションラベルを持つために、特定の文字列連結を実行できます。

例:

  • ng-options="item.ID as item.Title + ' - ' + item.ID for item in items" 次のようなラベルが表示されます Title - ID
  • ng-options="item.ID as item.Title + ' (' + item.Title.length + ')' for item in items"以下のようにあなたがラベル与えTitle (X)ところ、Xタイトル文字列の長さがあります。

たとえば、フィルターを使用することもできます。

  • ng-options="item.ID as item.Title + ' (' + (item.Title | uppercase) + ')' for item in items"のようなラベルTitle (TITLE)が表示されます。ここで、TitleプロパティとTITLEのTitle値は同じ値ですが、大文字に変換されます。
  • ng-options="item.ID as item.Title + ' (' + (item.SomeDate | date) + ')' for item in items"Title (27 Sep 2015)モデルにプロパティがある場合、のようなラベルが表示されますSomeDate

7

CoffeeScriptの場合:

#directive
app.directive('select2', ->
    templateUrl: 'partials/select.html'
    restrict: 'E'
    transclude: 1
    replace: 1
    scope:
        options: '='
        model: '='
    link: (scope, el, atr)->
        el.bind 'change', ->
            console.log this.value
            scope.model = parseInt(this.value)
            console.log scope
            scope.$apply()
)
<!-- HTML partial -->
<select>
  <option ng-repeat='o in options'
          value='{{$index}}' ng-bind='o'></option>
</select>

<!-- HTML usage -->
<select2 options='mnuOffline' model='offlinePage.toggle' ></select2>

<!-- Conclusion -->
<p>Sometimes it's much easier to create your own directive...</p>

1
あなたのことradixを忘れないでくださいparseInthttp
//davidwalsh.name/parseint-radix

6

オプションごとにカスタムタイトルが必要な場合ng-optionsは、該当しません。代わりng-repeatにオプションを使用してください:

<select ng-model="myVariable">
  <option ng-repeat="item in items"
          value="{{item.ID}}"
          title="Custom title: {{item.Title}} [{{item.ID}}]">
       {{item.Title}}
  </option>
</select>

3

以下があなたの役に立つことを願っています。

<select class="form-control"
        ng-model="selectedOption"
        ng-options="option.name + ' (' + (option.price | currency:'USD$') + ')' for option in options">
</select>

1

それは便利です。バインディングは常に機能するとは限りません。

<select id="product" class="form-control" name="product" required
        ng-model="issue.productId"
        ng-change="getProductVersions()"
        ng-options="p.id as p.shortName for p in products"></select>

たとえば、RESTサービスからオプションリストのソースモデルを入力します。選択された値はリストを埋める前にわかっていて、設定されました。$ httpでRESTリクエストを実行した後、リストオプションが実行されます。

ただし、選択したオプションは設定されていません。未知の理由により、シャドウ$ digestのAngularJSは、選択されたとおりにバインドされません。選択を設定するには、jQueryを使用する必要があります。重要です!AngularJSは、影で、ng-repeatオプションによって生成されたattr "value"の値にプレフィックスを追加します。intの場合は「number:」です。

$scope.issue.productId = productId;
function activate() {
    $http.get('/product/list')
       .then(function (response) {
           $scope.products = response.data;

           if (productId) {
               console.log("" + $("#product option").length);//for clarity
               $timeout(function () {
                   console.log("" + $("#product option").length);//for clarity
                   $('#product').val('number:'+productId);

               }, 200);
           }
       });
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.