May 28, 2013

KnockoutJS - checkbox與textbox混搭應用 (2)

KnockoutJS - checkbox與textbox混搭應用 (1),我們希望在使用者輸入完資料到textbox後,表單控制項下方可直接顯示輸入結果,並且在取消勾選checkbox時,將textbox中的資料與下方輸入結果一併清空。

建立ViewModel
function ViewModel() {
    var self = this;
    self.hasOther = ko.observable(false);
    self.other = ko.observable("");
}

ko.applyBindings(new ViewModel());
新增了other屬性,用來存放textbox之值。

建立Data Bindings
<label>
    <input type="checkbox" data-bind="checked: hasOther" />Others:</label>
<input type="text" data-bind="value: other, valueUpdate: 'afterkeydown', 
                                enable: hasOther, hasfocus: hasOther()" />
<div data-bind="text: other"></div>
textbox中,我們新增了value binding及它的參數valueUpdate,並設為afterkeydown,表示當使用者一按下鍵盤,KnockoutJS就隨即把textbox中的資料更新到ViewModel的other屬性裡。而在表單控制項下方我們佈置了一個div,設定其text binding,如此當other屬性一有更新,KnockoutJS就隨即更新UI。

看一下執行結果,在textbox中一輸入資料,所輸入的資料就馬上顯示在下方的div區塊裡。

到目前為止,已完成了前半段需求 - 在使用者輸入完資料到textbox後,表單控制項下方可直接顯示輸入結果,接下來要實作後半段需求 - 取消勾選checkbox時,將textbox中的資料與下方輸入結果一併清空

實作這個需求,有兩種可行方式。第一種從View來著手,另一種則是從ViewModel來達成。

View
<label>
    <input type="checkbox" data-bind="checked: hasOther" />Others:</label>
<input type="text" data-bind="value: hasOther() ? other : '', valueUpdate: 'afterkeydown',
                                enable: hasOther, hasfocus: hasOther()" />
<div data-bind="text: hasOther() ? other() : ''"></div>

value binding修改為 hasOther() ? other : '',表示checkbox被取消勾選時,hasOther會被設為false,textbox的值就會是空的。div裡的text binding也是相同道理。從http://jsfiddle.net/z4YJe/5/可以看到執行結果,在checkbox取消勾選時,textbox被disabled外,其值被清除,下方div區塊內的資料也不會顯示出來。不過當再次勾選checkbox時,會發現之前輸入的資料又顯示出來了,這是因為我們只是在顯示資料上作手腳,實際上ViewModel裡的資料還存在,KnockoutJS馬上就透過data binding將資料顯示在UI上。

ViewModel

要徹底清除資料的話需從ViewModel著手,只要清除了other屬性內的資料,當資料繫結到UI時就會是清空的狀態。但要如何在checked或是enable binding中,讓textbox及div裡的資料清空?透過subscribe函式訂閱hasOther屬性。
    <input type="checkbox" data-bind="checked: hasOther" />Others:</label>
<input type="text" data-bind="value: other, valueUpdate: 'afterkeydown',
                                enable: hasOther, hasfocus: hasOther()" />
<div data-bind="text: other"></div>

function ViewModel() {
    var self = this;
    self.hasOther = ko.observable(false);
    self.hasOther.subscribe(function (newValue) {
        if (!newValue) {
            self.other('');
        }
    });

    self.other = ko.observable("");
}

ko.applyBindings(new ViewModel());

在subscribe函式中,檢查hasOther被更新的值為false時,將other屬性值清空,textbox及div內的資料就會一併清空。執行結果可參考http://jsfiddle.net/z4YJe/6/

No comments: