下拉選單<select>也是網頁設計重要的一環,knockout.js(以下簡稱KO)也有不錯的支援。針對<select>,在data-bind除了用value可對應下拉選單的選取結果,其選項也可以由ViewModel中取得,甚至動態改變。以下是<select>常用的data-bind參數:

  1. options:
    指向陣列或ko.observableArray(),KO會將陣列元素轉換為下拉選項。如果是ko.observableArray(),當動態增加或移除陣列元素時,下拉選項也會馬上跟著增減。
  2. optionsText, optionsValue:
    用來產生下拉選項的陣列元素可以是具有多個屬性的JavaScript物件,透過optionText, optionValue設定屬性名稱字串,我們可以指定用哪個屬性當成<option>的文字內容,哪個屬性當成value。
  3. value:
    指向ViewModel的特定屬性,屬性一般以ko.observable()宣告。如此當下拉選單選取新值,所選的<option> value值會更新到ViewModel屬性上;而一旦該屬性被程式修改或因使用者輸入改變,下拉選單也會自動切到新值對應的<option>選項上。
  4. selectedOptions:
    針對可多選(multiple)的<select>,selectedOptions可繫結到ko.observableArray()型別屬性,該陣列使會即時反應使用者所選取的項目集合;而變更該obervableArray陣列的元素項目,也會立刻變更對應option的selected狀態。

範例2是一個簡單應用展示,ViewModel定義了selectOptions陣列(假設選項不會動態變化,故用一般陣列即可,不用ko.observableArray),陣列元素物件各有t、v兩個屬性分別當作<option>的文字跟值,而下拉選單的選取結果要反應到result這個ko.observable()屬性上。於是<select>的data-bind寫法如下:

<select id="selOptions" style='width: 120px'
data-bind="options: selectOptions, optionsText: 'text', optionsValue: 'value', value: result">

為了觀察選取結果,再增加一個<span data-bind="text: result">即時反應result內容。

另外我們宣告一個chageToPhone()函數,將result的值強制指定為"Phone",並用<input type="button" value="Set Phone" data-bind="click: changeToPhone" />設定成點擊時觸發,藉以觀察是否修改result為Phone,下拉選單也會自動跳到Phone選項上。

程式碼如下,線上展示在此。

<!DOCTYPE html>
 
<html>
<head>
    <title>Lab 2 - 對應下拉選單</title>
    <script src="../Scripts/jquery-1.7.2.js"></script>
    <script src="../Scripts/knockout-2.1.0.debug.js"></script>
    <script>
        function MyViewModel() {
            var self = this;
            //宣告一個物件陣列用來提供select的選項
            self.selectOptions = [
                    { t: "PC", v: "PC" },
                    { t: "Notebook", v: "NB" },
                    { t: "Phone", v: "Phone" }
                ];
            self.result = ko.observable("PC");
            self.changeToPhone = function () {
                //ko.observable()宣告的屬性,
                //使用propName("...")方式改變其值,
                //才能通知相關UI產生連動效果
                self.result("Phone");
            };
        }
        $(function () {
            ko.applyBindings(new MyViewModel());
        });
    </script>
</head>
<body>
<!-- 額外指定options來源,option text/value對應的屬性名稱 -->
<select 
data-bind="options: selectOptions, optionsText: 't', optionsValue: 'v', value: result">
</select><br />
<span data-bind="text: result"></span><br />
<!-- 指定按鈕click事件呼叫ViewModel中的特定函數修改result值 -->
<input type="button" value="Set Phone" data-bind="click: changeToPhone" />
</body>
</html>
[KO系列]
http://www.darkthread.net/kolab/labs/default.aspx?m=post

Comments

# by 黑月

練習至此,有個疑問油然而生想請教版主, vm(viewmodel)只能設計一個?若設計多個 vm 似乎屬性名稱不能重覆(如何繫結不同 vm 但相同名稱的屬性 )

# by Jeffrey

to 黑月,同一個網頁可以並存多個ViewModel,並使用ko.applyBindings(viewMode1, document.getElementById("element1"));將不同ViewModel繫結到網頁的不同容器。至於不同ViewModel但屬性名稱重複的問題我不太能理解,還需要詳細一點的描述。

Post a comment