復刻對象: KO範例2 - 下拉選單

在NG,下拉選單(<select>)跟<input>一樣用ng-model="..."建立雙向繫結,如要透過繫結動態產生選項,可用ng-options Directive。ng-options的語法較特別,需穿插as for in等關鍵字,寫法又有好幾種,保哥有篇詳解可參考。若以物件陣列為資料來源,有兩種做法:

1) 繫結到物件本身: "選項文字 for 物件變數 in 選項物件陣列"
2) 分別繫結文字及值: "選項值 as 選項文字 for 物件變數 in 選項物件陣列"

其中物件變數是ng-options就地新增的變數名稱,不需要事先定義在ViewModel中。若採取第一種做法,ng-model="model.result"繫結的對象會是物件,而非<option value="…">的value,因此下方要寫成<span ng-bind="model.result.t">才會顯示選項文字,而changeToPhone()中,也是透過指定物件改變選取結果: self.result = self.options[2] 。

按鈕事件用ng-click指定要執行的JavaScript函式,記得要加上括號,寫成ng-click="model.changeToPhone()"。

程式範例如下: Live Demo

排版顯示純文字
<!DOCTYPE html>
<html ng-app="sampleApp">
<head>
  <meta charset="utf-8">
  <title>Lab 2 - 對應下拉選單</title>
</head>
<body ng-controller="defaultCtrl">
<select ng-options="item.t for item in model.options" ng-model="model.result" >
</select><br />
<span ng-bind="model.result.v"></span><br />
<input type="button" value="Set Phone" ng-click="model.changeToPhone()" />
  <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.14/angular.js"></script>
  <script>
    angular.module("sampleApp", [])
    .controller("defaultCtrl", function($scope) {
      function myViewModel() {
        var self = this;
        self.options = [
                    { t: "PC", v: "PC" },
                    { t: "Notebook", v: "NB" },
                    { t: "Phone", v: "Phone" }
        ];
        self.result = self.options[0];
        self.changeToPhone = function() {
          self.result = self.options[2];
        }
      }
      $scope.model = new myViewModel();
    });
  </script>
</body>
</html>

接著來看繫結選項文字及選項值的第二種做法: Live Demo

排版顯示純文字
<body ng-controller="defaultCtrl">
<select ng-options="item.v as item.t for item in model.options" ng-model="model.result" >
</select><br />
<span ng-bind="model.result"></span><br />
<input type="button" value="Set Phone" ng-click="model.changeToPhone()" />
  <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.14/angular.js"></script>
  <script>
    angular.module("sampleApp", [])
    .controller("defaultCtrl", function($scope) {
      function myViewModel() {
        var self = this;
        self.options = [
                    { t: "PC", v: "PC" },
                    { t: "Notebook", v: "NB" },
                    { t: "Phone", v: "Phone" }
        ];
        self.result = "NB";
        self.changeToPhone = function() {
          self.result = "Phone";
        }
      }
      $scope.model = new myViewModel();
    });
  </script>
</body>

其中,ng-options被寫成"item.v as item.t for item in model.options",定義用item.v做為選項值,item.t做為選項文字。model.result的繫結對象也就變成了選項值,要指定result直接寫字串就好,例如: self.result = "Phone"。

[NG系列]
http://www.darkthread.net/kolab/labs/default.aspx?m=post&t=angularjs

Comments

# by kkman021

黑暗大你好, 我最近也在學AngularJS,也跟隨著你的腳步。 關於下拉選單有個問題想問在AngularJS是否有更好的解法。 下拉選單往往資料庫是存放ID值而非文字,如此在顯示明細時該欄位應該是對照ID去顯示文字。 我找到了一種方式,但覺得似乎不是太直覺。 我寫的模擬程式:http://jsbin.com/jeheyuvu/2/

# by Jeffrey

to kkman021, 我建議改成這樣: http://jsbin.com/jeheyuvu/3/edit,ng-options改成Insterest.name for Insterest in ListInsterest,把原本的as拿掉,<select>的選取組果繫結到Selected,之後可以用Selected.id取編號、Selected.name取文字,如果要當成欄位PostBack,<input type="hidden" ng-value="Selected.id">即可。

# by kkman021

感謝黑大的回覆。 另外,想問黑大是否有研究到,針對顯示明細時,透過某一個ID值顯示陣列中的Value值的方法!? 我最近寫了一個範例:http://jsbin.com/jiyohe/1/edit 主要想解決像是JSBin Table中顯示的職業欄位和興趣欄位的方式,總感覺應該有更好的寫法,尤其顯示興趣欄位,還找不到方式去除最後的顯示符號方式感覺不是正統的寫法。 不曉得黑大是否有相關的想法??

# by Jeffrey

to kkman021, 類似你所舉的案例,我習慣宣告一個Employee類別,把興趣、職業由id轉name的功能封裝進Employee類別中。至於串接陣列且最後一項不顯示",",我通常會用.join(", ")達成。http://jsbin.com/pomiq/1/edit

# by kkman021

太感謝黑大了!!

Post a comment