網頁

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

    回覆刪除