我們在 AngularJS 入門教學 - ngOptions(一) 中學會如何將最基本的陣列透過 ng-options 來產生下拉選單的選項。那如果陣列中存放的是物件的話呢?
讓我們先來產生好 Controller 及 Model:
1 2 3 4 5 6 7 8 9 10 11 12 13 | var SelectCtrl = function($scope) { $scope.onepiece = [{ name: '蒙其·D·魯夫', age: 19, skills: [ '橡膠槍', '橡膠火箭砲', '換檔', '霸氣' ] }, // 略... { name: '布魯克', age: 90, skills: [ '催眠曲·輪舞', '鼻唄三丁·矢筈斬', '冰凍劍', '哼歌·吹雪斬' ] }]; }; |
onepiece 雖然一樣也是陣列,但其它存放的元素都是一個有 3 個屬性的物件,接下來筆者要將陣列中的元素一一輸出在下拉選單中。讓我們先來看我們的 View:
1 2 3 4 5 6 7 | <div class="alert alert-info"> <select ng-model="role"> <option value="">--請選擇角色--</option> </select> <div ng-show="role!=null">選擇的是:{{ role }}</div> </div> |
Select 下拉選單綁定到 role 上,然後 div 的顯示與否是依 role 的值是否為 null 來決定的。
接下來就讓我們來看看 ng-options 對於存放物件的陣列的 4 種不同用法吧。
label for value in array
1 2 3 | <select ng-model="role1" ng-options="member.name for member in onepiece"> <option value="">--請選擇角色--</option> </select> |
這邊看到的第 2 個 member 是指被取出的每一個物件(value),而第 1 個 member.name 就是指說要用來當做文字顯示的 label 是來自第 2 個 member 物件中的 name 屬性。
來看看展開下拉選單後的樣式:
當選擇到某個項目時:
ㄟ...還記得嗎?剛剛就有提到說 value 是一個 member 物件,所以把物件直接用 Angular 表達式(Angular Expressions)的話,就會被用 json 過濾器(Filters)來進行轉換。所以就變成我們現在看到的結果啦!
所以,我們在使用時可以利用物件的方式來取用:
1 | <div ng-show="role!=null">選擇的是:{{ role.name + '(' + role.age + ')' }}</div> |
再試一次,結果就會更直覺囉:
從這邊可以看到 role 的值預設就是陣列中的物件,如果想要指定選擇後的值時,可以再搭配一個 select。
select as label for value in array
1 2 3 | <select ng-model="role" ng-options="member.name as (member.name + '(' + member.age + ')') for member in onepiece"> <option value="">--請選擇角色--</option> </select> |
這邊的第 1 個 member.name 就是當某一個選項被選擇(select)後所要對應的值。而 as 到 for 之間的算是 Angular 表達式(Angular Expressions),可以用使用一些複雜的語法來組合出顯示用的文字內容。
展開下拉選單後的樣式:
這邊筆者是把名字及年齡組合成字串來當做下拉選單的選項內容,但當某個選項被選到之後,因為被指定的 select 是 member.name 而不是原本的 member 物件喔。
所以這邊的 View 只要直接顯示 role 就可以了:
label group by group for value in array
1 2 3 | <select ng-model="role" ng-options="member.name group by member.age for member in onepiece"> <option value="">--請選擇角色--</option> </select> |
這其實就是使用 group by 來指定用 member.age 屬性來將選項分組,分組的效果其實就是 optgroup 的語法而已。
展開下拉選單後的樣式:
當選擇到某個項目時:
select as label group by group for value in array track by trackexpr
1 2 3 | <select ng-model="role" ng-options="member as member.name group by member.age for member in onepiece track by member.age"> <option value="">--請選擇角色--</option> </select> |
最後一種就是既有分組,也有自定值,其實就是將前面的幾種方式都組合在一起而已。不過,針對陣列中的物件元素來說的話,還多了一個很特別的 Angular 表達式(Angular Expressions) - track by。
這是可以用來自訂一個屬性用來區別每一個物件是唯一的,假設筆者現在是用 member.age 來區別物件,所以若是值一樣的話,就都會以第一個為主。
展開下拉選單後的樣式:
當選擇到同群組的某個項目時:
再看所產生出來的 HTML:
有看到了嗎?這邊就是用 person.age 來當值,所以選到同群組的選項時,該群組中的第一個選項再怎麼點選都是選到第二個,但值都是以第一個的為主。
所以雖然一樣都是以陣列為主,但隨著裡面存放的元素型態不同而會有不同的使用方式喔!那如果 Model 本身的內容是物件而不是陣列的話呢?這...就等下一篇來說明囉!