June 7, 2013

KnockoutJS - radio button應用(2)

使用foreach binding顯示多個radio button 
有時radio button是動態產生的,如根據資料庫取得的資料來顯示對應的radio button,這時就需要搭配foreach binding來產生radio button。
<div data-bind="foreach: techniques">
    <label>
        <input type="radio" data-bind="value: value, checked: $parent.selectedTechnique" />
        <span data-bind="text: text"></span>
    </label>
</div>

<div data-bind="text: selectedTechnique"></div>
function ViewModel() {
    var self = this;
    self.techniques = [{
        text: "ASP.NET Web Forms",
        value: "webforms"
    }, {
        text: "ASP.NET MVC",
        value: "mvc"
    }, {
        text: "ASP.NET Web API",
        value: "webapi"
    }];

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

ko.applyBindings(new ViewModel());

techniques為陣列,可以是資料庫取出的資料,selectedTechnique則為使用者選取的radio button之值。在View中,selectedTechnique需透過$parent$root取得,因為在foreach binding中的binding context與selectedTechnique的binding context不同。執行結果可參考



透過陣列取得選項文字
由上面執行結果可看出selectedTechnique顯示的是radio button之,如果想要顯示radio button的選項文字,可參考KnockoutJS - radio button應用(1)一文使用jQuery搭配KnockoutJS的subscribe功能取得選項文字。還有另一種方式不需使用到jQuery操作DOM來取得選項文字,而是透過KnockoutJS的utils函式庫搜尋techniques陣列,找出radio button值相對應的選項文字。
<div data-bind="foreach: techniques">
    <label>
        <input type="radio" data-bind="value: value, checked: $parent.selectedTechnique" />
        <span data-bind="text: text"></span>
    </label>
</div>

<div data-bind="text: selectedTechniqueText"></div>
function ViewModel() {
    var self = this;
    self.techniques = [{
        text: "ASP.NET Web Forms",
        value: "webforms"
    }, {
        text: "ASP.NET MVC",
        value: "mvc"
    }, {
        text: "ASP.NET Web API",
        value: "webapi"
    }];

    self.selectedTechnique = ko.observable("");

    self.selectedTechniqueText = ko.computed(function () {

        var search = self.selectedTechnique().toLowerCase();

        if (!search) {

            return null;

        } else {

            var matchedItem = ko.utils.arrayFirst(self.techniques, function (item) {
                return ko.utils.stringStartsWith(item.value.toLowerCase(), search);
            });

            return matchedItem.text;
        }
    });
}

ko.applyBindings(new ViewModel());

上面程式碼片段是由Utility Functions in KnockoutJS一文中的Searching for an item in the array章節修改而來,因為KnockoutJS的官網並未放上utils函式庫的參考文件。有一點要特別注意的是,stringStartsWith函式在KnockoutJS release的版本中並未被放入,但在debug的版本有,所以在使用時需手動複製加入

執行結果



使用Virtual Element控制radio button選項文字
在前個例子中,radio button的選項文字是透過span標籤加上text binding達成,我們也可以透過KnockoutJS的Virtual Element以註解方式將radio button的選項文字加入。
<div data-bind="foreach: techniques">
    <label>
        <input type="radio" data-bind="value: value, checked: $parent.selectedTechnique" />
         <!--ko text: text--><!--/ko-->
    </label>
</div>
<div data-bind="text: selectedTechnique"></div>


使用template binding顯示多個radio button
除了使用foreach binding外,也可以再額外搭配template binding讓radio button可以重複使用。template內為要重複顯示的資料,div中template binding的name屬性值需與script中的id屬性值相同。如同前面的例子所述,selectedTechnique需透過$parent$root取得,因為在foreach binding中的binding context與selectedTechniques的binding context不同。
<div data-bind="template: { name: 'multipleradibuttons', foreach: techniques }"></div>
<script type="text/html" id="multipleradibuttons">
    <label>
        <input type="radio" data-bind="value: value, checked: $parent.selectedTechnique" />
        <!--ko text: text--><!--/ko-->
    </label>
</script>
<div data-bind="text: selectedTechnique"></div>

其它應用
KnockoutJS - radio button與textbox混搭應用

No comments: