2013年11月12日 星期二

ASP.NET MVC 資料分頁 - 使用 PagedList.Mvc:Table 的 Checkbox

這一篇的文章標題不太好設定,我想大家應該看得懂,簡單說就是當我們所呈現的資料用 Table 來表示時,如果有需要是要在每個橫列加上 Checkbox,如何在每次分頁後去保留各個分頁的 Checkbox 狀態呢?

這個需求的解決方式有很多種,不過我這邊將會延續上一篇「ASP.NET MVC 資料分頁 - 使用 PagedList.Mvc:AJAX」的內容,我會在前端使用 Javascript 的方式來解決這個需求。

 


Step.1

首先,先在 _PagedAjax.cshtml 內的 Table 裡加上 Checkbox,包含 th, td 都要加入 Checkbox,

image

image

執行結果

image

 

Step.2

上一個步驟只是在頁面上加入 Checkbox 而已,還沒有加入行為,所以這邊先對 table header 的 Checkbox 加入行為,也就是勾選 table header 的 Checkbox 時可以全選或全部取消該頁的 Checkbox 狀態。

在 Order/Index.cshtml 裡增加 Javascript 程式,

image

然後在 fetchPage() 裡加入 CheckBoxsEventHandler 的使用,

image

不過這邊會有個地方要做個修改,就是當我們全勾選該頁所有的 Checkboxs 時,假如其中一個 Checkbox 更改為取消勾選時,這時候 table header 的 Checkbox 就必須修改為未勾選的狀態,

image

 

Step.3

完成 Checkbox 的行為後,再來就是要紀錄下每次勾選的資料,我們將勾選的資料紀錄在 Array 中,變更勾選狀態有兩種行為要處理,一個是都勾選時要將新增資料到 Array,另一個是取消勾選時要將 Array 裡的資料給移除,

image

UpdateCheckedValue() 更新已勾選資料

image

GetCheckedValues() 取得有勾選的項目, GetUnCheckedValues() 取得未勾選的項目,

image

將 UpdateCheckedValue() 加入到 Checkbox 的勾選行為裡,

image

 

Step.4

我們已經將勾選後的值給儲存到前端的 Array 裡,接著就是在每次 AJAX 更換分頁內容的時候要更新該分頁裡的 Checkbox 狀態,

image

我們在 fetchPage() 這個 function 加入呼叫 ChangeCurrentPageCheckboxStatus(),

image

 

Step.5

到 Step.4 就已經完成了需求的功能,但這邊還是畫蛇添足地再加一個簡單的功能,就是取得這些分頁所勾選的 Checkbox 值。

在 Index.cshtml 裡加入一個 button,

image

再加入 Button 的行為,取得存於 Array 中的 Checkbox 勾選的資料並且顯示,

image

 

完整前端程式內容

$(function() {
    var page = window.location.hash
        ? window.location.hash.slice(1)
        : 1;
    fetchPage(page);
    
    $('#ButtonGetCheckedValues').click(function () {
        if (checkedValueArray.length == 0) {
            alert('Empty');
        }
        else {
            var result = checkedValueArray.join(',');
            alert('Checked Values: ' + result);
        }
    });
});
 
var fetchPage = function(page) {
    var pagedPartialUrl = '@Url.Action("PagedPartial", "Order")';
    $.get(pagedPartialUrl, { page: page }, function(data) {
        window.location.hash = page;
        $('#OrderData').html(data);
        $('#OrderData .pagination li a').each(function (i, item) {
            var hyperLinkUrl = $(item).attr('href');
            if (typeof hyperLinkUrl !== 'undefined' && hyperLinkUrl !== false) {                        
                var pageNumber = $(item).attr('href').replace('/Order?page=', '');
                $(item).attr('href', '#').click(function(event) {
                    event.preventDefault();
                    $(event.target).attr('href');
                    fetchPage(pageNumber);
                });
            }
        });
        
        CheckeBoxsEventHandler();
        ChangeCurrentPageCheckboxStatus();
    });
};
 
var CheckeBoxsEventHandler = function () {
    $('th input:checkbox').click(function () {
        $('td input:checkbox').prop(
            'checked',
            $('th input:checkbox').is(':checked')
        );
        UpdateCheckedValue();
    });
    
    $('td input:checkbox').change(function () {
        $('th input:checkbox').prop(
            'checked',
            $('td input:checkbox:checked').length == $('td input:checkbox').length
        );
        UpdateCheckedValue();
    });
};
 
//儲存已勾選的 Checkbox 值
var checkedValueArray = [];
 
var UpdateCheckedValue = function () {
    //Add
    var currentPageCheckedValues = GetCheckedValues();
    if (checkedValueArray.length == 0) {
        $.each(currentPageCheckedValues, function (i, item) {
            checkedValueArray.push(item);
        });
    } else {
        $.each(currentPageCheckedValues, function (i, item) {
            var count = 0;
            $.each(checkedValueArray, function (index, element) {
                if (element == item) { count++; }
            });
            if (count == 0) {
                checkedValueArray.push(item);
            }
        });
    }
 
    //Remove
    var currentPageUnCheckedValues = GetUnCheckedValues();
    if (currentPageUnCheckedValues.length > 0) {
        $.each(currentPageUnCheckedValues, function (i, item) {
            checkedValueArray = $.grep(checkedValueArray, function (element, j) {
                return element != item;
            });
        });
    }
};
 
var GetCheckedValues = function () {
    return $('input:checkbox[name=checkboxs]:checked').map(function () {
        return $(this).val();
    }).get();
};
 
var GetUnCheckedValues = function () {
    return $('input:checkbox[name=checkboxs]:not(:checked)').map(function () {
        return $(this).val();
    }).get();
};
 
var ChangeCurrentPageCheckboxStatus = function () {
    var currentPageCheckBoxValues =
        $('input:checkbox[name=checkboxs]').map(function() {
            return $(this).val();
        }).get();
 
    var count = 0;
    $.each(currentPageCheckBoxValues, function (i, item) {
        $.each(checkedValueArray, function (index, element) {
            if (item == element) {
                count++;
                $('input:checkbox[name=checkboxs][value=' + item + ']')
                    .prop('checked', 'checked');
            }
        });
    });
 
    $('th input:checkbox').prop(
        'checked',
        count == $('input:checkbox[name=checkboxs]').length
    );
};

 

操作畫面

20131111_PagedListMvc_AJAX_Checkbox

 


當分頁然後有 Checkbox 時要保留勾選狀態也有其他的作法,我這篇文章的作法只是其中一種,實做的內容雖然不是很嚴謹,但也可以作為一種參考。

 

以上

5 則留言:

  1. 請問一下:

    以ASP.NET MVC延伸此範例,將checkbox選取的資料匯出成text檔,有實際的範例可以參考嗎?

    謝謝

    回覆刪除
    回覆
    1. 我這邊沒有所謂的實際範例,不過很容易做得出來,這一篇已經可以將 Gird 裡所勾選的資料給抓出來了,
      那麼這些勾選的資料 ID 就可以 POST 回到後端,然後在後端就可以抓到這些 ID 的資料,然後再匯出來,
      怎麼匯出來,不論是 EXCEL 還是 CVS 或是單純的 txt 檔案,網路上就可以找到許多現成的範例,
      以匯出 Excel 來說,這個部落格裡就有「ASP.NET MVC 匯出 Excel 簡單做 - 使用 ClosedXML」這一篇做說明,
      另外也可以善用 Google,尋找 ASP.NET MVC Export CSV 或是 ASP.NET MVC Exprot txt,都可以找到,
      自己的問題自己解,印象會相當深刻喔 ^.<

      刪除
  2. 作者已經移除這則留言。

    回覆刪除
  3. can you please send me the full example, I trird and it doesn't work

    回覆刪除

提醒

千萬不要使用 Google Talk (Hangouts) 或 Facebook 及時通訊與我聯繫、提問,因為會掉訊息甚至我是過了好幾天之後才發現到你曾經傳給我訊息過,請多多使用「詢問與建議」(在左邊,就在左邊),另外比較深入的問題討論,或是有牽涉到你實作程式碼的內容,不適合在留言板裡留言討論,請務必使用「詢問與建議」功能(可以夾帶檔案),謝謝。