KO範例6 - 陣列元素的新增/移除事件

範例4已展示KO完全掌握observableArray()陣列元素增減,即時反應在UI的能力。但如果我們希望在陣列增加或移除元素時加上自訂邏輯,要怎麼做?

foreach提供了afterAdd及beforeRemove兩個額外的事件繫結設定,允許在陣列新增、移除元素時執行特定邏輯。在此繼續沿用先前的使用者清單呈現範例,加上兩個效果:

  • 新增資料時,將最新加入的資料標為暗紅字
  • 刪除資料時,加上資料淡出後消失的特效

而在ViewModel裡我們加上兩個函數:

            //第一次foreach產生時不會觸發,只有事後加入才會
            self.afterAddEvent = function (elems, idx, data) {
                //Template中的Text Node與Element Node會分別觸發多次
                //在本例中會因Text, Element, Text共觸發三次
                //透過nodeType過濾,只處理Element Node
                if (elems.nodeType == 1) //Element Node
                {
                    $(".new").removeClass("new");
                    $(elems).addClass("new");
                }
            };
            //注意: 掛載beforeRemove事件後,要自已負責移除被刪除元素
            self.b4RemoveEvent = function (elems, idx, data) {
                if (elems.nodeType == 1) {
                    $(elems)
                    .css("background-color", "red")
                    .animate({ opacity: 0.2 }, 500, function () {
                        $(this).remove();
                    })
 
                }
            };

afterAdd及beforeRemove函數會固定收到三個參數,elems、index及data,其中elems為範本容器中的各元素,在本範例中,就是以下黃底紅字部分:

<tbody data-bind="foreach: { data: users, afterAdd: afterAddEvent, beforeRemove: b4RemoveEvent }">
    <tr>
        <td><span data-bind="text: id"></span></td>
        <td><span data-bind="text: name"></span></td>
        <td><span data-bind="text: score" style='text-align: right'></span></td>
        <td><a href='#' data-bind="click: $root.removeUser">移除</a></td>
    </tr>

</tbody>

但此處有個小訣竅,實際運作時afterAdd/beforeRemove會收到不同的elems被呼叫三次,原因是除了<tr>之外,<tbody>到<tr>之間的空白、</tr>到</tbody>間的空白也各算一個Element,其nodeType為3,代表TEXT_NODE。因此三次傳入的elems分別為TEXT_NODE、ELEMENT_NODE、TEXT_NODE,而第二次傳入的ELEMENT_NODE是<tr>…</tr>間的內容,才是我們需要處理的對象,故加入if (elems.nodeType == 1)的判斷式。

最新加入資料的特別標示,在此透過addClass("new")來達成;至於移除資料的特效,則先為<tr>加上不透明度(opacity)由100%降到20%的動畫,然後在動畫完成後,將其自<tbody>中移除。要注意,一旦掛載了beforeRemove,KO就不再自動幫你移除該筆資料在網頁對應的元素,必須自行處理,但這也提供開發人員絕對的控制權,可自由安排HTML元素要怎麼從網頁上退場。

線上展示


[KO系列]
http://www.darkthread.net/kolab/labs/default.aspx?m=post
歡迎推文分享:
Published 11 September 2012 07:27 AM 由 Jeffrey
Filed under:
Views: 11,850



意見

# 李政忠 said on 16 June, 2013 06:55 PM

你好,我想在template裡使用afterAdd事件時,卻一直無法成功,還請指點迷津,謝謝。

...

<div data-bind="template: { name: 'contactTmpl', foreach: members, afterAdd: afterAddEvent }"></div>

...

function MyViewModel() {

   ...

   self.afterAddEvent = function(element, index, data){

       console.log(index);

   };

}

# Jeffrey said on 17 June, 2013 10:04 AM

to 李政忠,經測試應該可行,請參考範例: jsfiddle.net/.../1 看看哪邊有差異

# Andy said on 19 September, 2018 03:28 AM

Dear 黑暗大

您好

我設計一個網頁,裡面有一些TextBox,其中還有如此範例的動態表格(可新增/刪除),當我按下儲存按鈕時,會把相對應的TextBox內容丟到我已建好的資料庫其指定的資料表裡面,我的問題如下:

我也想把count行數的那個值丟到資料表某個欄位(此範例圖片中共4筆==>的那個"4"這個值),asp.net要如何去抓它呢

還請大大指教,感謝

# Jeffrey said on 19 September, 2018 10:45 AM

to Andy, 如果你 ASP.NET 端是用 PostBack 方式取值,最簡單的做法是將 4 放入 <input type="hidden" name="fldCount" data-bind="value: ..." />,後端用 Request["fldCount"] 接回數字。

# Andy said on 20 September, 2018 05:47 AM

Dear 黑暗大

感謝您,已成功將count後的數值寫入資料庫

利用您提供的方法,也將動態表格內user所填/選的資料成功寫入資料庫了

你的看法呢?

(必要的) 
(必要的) 
(選擇性的)
(必要的) 
(提醒: 因快取機制,您的留言幾分鐘後才會顯示在網站,請耐心稍候)

5 + 3 =

搜尋

Go

<September 2012>
SunMonTueWedThuFriSat
2627282930311
2345678
9101112131415
16171819202122
23242526272829
30123456
 
RSS
創用 CC 授權條款
【廣告】
twMVC
最新回應

Tags 分類檢視
關於作者

一個醉心技術又酷愛分享的Coding魔人,十年的IT職場生涯,寫過系統、管過專案, 也帶過團隊,最後還是無怨無悔地選擇了技術鑽研這條路,近年來則以做一個"有為的中年人"自許。

文章典藏
其他功能

這個部落格


Syndication