上一篇「ASP.NET MVC 3 資料套用範本 - 使用jQuery.Templates」介紹了如何在ASP.NET MVC 3中使用jQuery.Templates,
而本部落格也有一系列的分頁文章「資料分頁」,所以這一次就來介紹如何在ASP.NET MVC 3中使用jQuery.Templates完成分頁的功能,
其實要取得分頁的資料來源是比較容易的,只要在後端處理好每次要取得分頁的資料量與資料內就可以,
之前一系列「資料分頁」的文章中,我有建立了一個有關生成Pager的HtmlHelper,
而每一次的分頁不管是GET方式還是POST,從前端傳送需求到後端,後端會連同Pager的內容也一併生成且送回到前端顯示,
因為我們使用jQuery.Templates所使用的資料是JSON,只會是包含分頁資料本身,也就是說頁面上的Pager我們要在前端處理,
本篇文章將會在前端使用「jQuery Pagination Plugin」來做為前端的Pager,以作為我們前端分頁操作介面的解決方案。
jQuery Pagination Plugin
http://blog.ajaxmasters.com/jquery-pagination-plugin/
Demo:http://tutorials.ajaxmasters.com/pagination-demo/
其實jQuery Plugins中有關分頁的套件相當地多,有的功能與介面UI甚至比這一個好很多,那為何要介紹這個來使用呢?
一、介面與原本我們所使用的MvcPaging相似
二、在頁面上的使用與整合還算簡單
這個套件的使用相當簡單,由下圖中的使用設定方式就可見一二,
對於要顯示分頁pager的容器設定pagination方法,方法的第一個參數是全部資料的數目,不是分頁資料數,
而第二個參數為一個option的內容,像這個範例的兩個option參數有「item_per_page」「callback」,
item_per_page,這個就是我們做分頁所會用到的page_size,每個分頁的資料數。
callback,這個就是要指定一個點選分頁後所要執行的callback方法,這個callback方法就是執行取得分頁資料以及顯示分頁資料內容。
來看看 jquery.pagination plugin 所預設的option參數內容:
opts = jQuery.extend({items_per_page: 10,num_display_entries: 10,current_page: 0,num_edge_entries: 0,link_to: "#",
prev_text: "Prev",
next_text: "Next",
ellipse_text: "...",
prev_show_always: true,
next_show_always: true,
callback: function () { return false; }}, opts || {});
這些預設值都可以讓我們做設定的修改,在 pagination()方法的option參數做指定就可以,以下說明幾個會需要修改的參數,
items_per_page:分頁數
num_display_entries:pager最多顯示的分頁數量
prev_text:顯示上一頁的文字
next_text:顯示下一頁的文字
prev_show_always:是否總是顯示上一頁
next_show_always:是否總是顯示下一頁
在進入主題之前,就先來看看我們所要完成的功能與操作是什麼樣子!
ASP.NET MVC 3 + jQuery.Templates + jQuery Pagination Plugin 完成分頁功能
Controller / Action 方法
這裡我們會建立三個Action方法,第一個是主要顯示頁面的Action方法,
public ActionResult PageMethod()
{
ViewData["CategoryDDL"] = categoryService.GenerateCategoryDDL(null);
return View();
}
第二個則是要取得選定分類下的產品總數,這是要給jquery.pagination方法的第一個參數來使用,
這個只會在選定分類並顯示該分類第一頁的資料時才會去執行,之後的分頁都不會執行這個Action,
[HttpPost]
public JsonResult ProductCount(string categoryId)
{
Dictionary<string, object> jo = new Dictionary<string, object>();
if (string.IsNullOrWhiteSpace(categoryId))
{
jo.Add("Msg", "Please Select a Category");
return this.Json(jo);
}
int id = 0;
bool parseResult = int.TryParse(categoryId, out id);
if (!parseResult)
{
jo.Add("Msg", "Wrong Category ID");
return this.Json(jo);
}
var result = this.productService.GetCollectionBy(id);
jo.Add("count", result.Count());
return this.Json(jo);
}
第三個Action方法則是取得指定分類以及指定分頁的分頁資料,
這一個Action方法取得分頁資料的地方是會使用到MvcPaging的ToPagedList()方法,
[HttpPost]
public JsonResult PageContent(int? page, string categoryId)
{
Dictionary<string, string> jo = new Dictionary<string, string>();
if (string.IsNullOrWhiteSpace(categoryId))
{
jo.Add("Msg", "Please Select a Category");
return this.Json(jo);
}
int id = 0;
bool parseResult = int.TryParse(categoryId, out id);
if (!parseResult)
{
jo.Add("Msg", "Wrong Category ID");
return this.Json(jo);
}
var result = this.productService.GetCollectionBy(id);
int currentPageIndex = page.HasValue ? page.Value - 1 : 0;
ViewData["CurrentPage"] = currentPageIndex;
var dataPaged = result.ToPagedList(currentPageIndex, 5);
List<Dictionary<string, object>> ja = new List<Dictionary<string, object>>();
foreach (var item in dataPaged)
{
Dictionary<string, object> product = new Dictionary<string, object>();
product.Add("ProductID", item.ProductID);
product.Add("ProductName", item.ProductName);
product.Add("SupplierID", item.SupplierID);
product.Add("CategoryID", item.CategoryID);
product.Add("QuantityPerUnit", item.QuantityPerUnit);
product.Add("UnitPrice", String.Format("{0:F}", item.UnitPrice));
product.Add("UnitsInStock", item.UnitsInStock);
product.Add("UnitsOnOrder", item.UnitsOnOrder);
product.Add("ReorderLevel", item.ReorderLevel);
product.Add("Discontinued", item.Discontinued);
ja.Add(product);
}
return this.Json(ja);
}
View
這邊先看View頁面中的HTML內容,JavaScript的內容稍後再看,
裡面要注意的是,有一個ID為「Panination」的DIV,這是用來顯示Pager的地方,
而Table的地方,只有設定thead的內容,而tbody的內容則會搭配jQuery.Templates來動態顯示分頁資料,
@{
ViewBag.Title = "PageMethod";
Layout = "~/Views/Shared/_Layout.cshtml";
}
@section HeadContent
{
<link href="@Url.Content("~/Content/pagination.css")" rel="stylesheet" type="text/css" />
}
<div id="TableContent" class="div_default">
<h2>PageMethod</h2>
<div id="formArea" style="width: 90%; margin-left: auto; margin-right: auto;">
Category:@Html.Raw(ViewData["CategoryDDL"].ToString())
<input type="button" id="ButtonSearch" value="List" />
</div>
<hr />
<p></p>
<div id="Information" style="display: none; width: 90%; margin-left: auto; margin-right: auto; background-color: #fffeee;">
Category:<span id="CategoryName" style="font-weight: bold;"></span>,
The number of products:<span id="ProductNumber" style="font-weight: bold;"></span>
<p></p>
</div>
<div id="Pagination" class="pagination" style="width: 90%; margin-left: auto; margin-right: auto;">
</div>
<br style="clear:both;" />
<table id="table1" class="grid" style="width: 90%; margin-left:auto; margin-right:auto; background-color: #fffeee;">
<thead>
<tr>
<th>
ProductID
</th>
<th>
ProductName
</th>
<th>
SupplierID
</th>
<th>
CategoryID
</th>
<th>
QuantityPerUnit
</th>
<th>
UnitPrice
</th>
<th>
UnitsInStock
</th>
<th>
UnitsOnOrder
</th>
<th>
ReorderLevel
</th>
<th>
Discontinued
</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<p></p>
</div>
jQuery.Template的分頁資料顯示範本
顯示分頁資料內容所使用,搭配jQuery.Templates,當AJAX取得JSON資料後,依照JSON的欄位資料並對應到範本上所指定的顯示位置,
每個顯示位置的參數名稱都須對照JSON的資料欄位名稱。
<script id="TemplateProduct" type="text/x-jquery-tmpl">
<tr id="tr_${ProductID}">
<td>
${ProductID}
</td>
<td>
${ProductName}
</td>
<td>
${SupplierID}
</td>
<td>
${CategoryID}
</td>
<td>
${QuantityPerUnit}
</td>
<td>
${UnitPrice}
</td>
<td>
${UnitsInStock}
</td>
<td>
${UnitsOnOrder}
</td>
<td>
${ReorderLevel}
</td>
<td>
${Discontinued}
</td>
</tr>
</script>
JavaScript程式內容
開頭
一開始除了在document.ready方法去設定頁面上指定element的操作外,我們也設定了四個全域參數,
這四個全域參數依序分別是,指定分頁數、分類產品總數、分類ID、分類名稱。
在接下來的function中會使用到這四個全域參數來存放資料。
var pageSize = 5;
var totalCount = 0;
var selected_Category_ID = '';
var selected_Category_Text = '';
$(document).ready(function ()
{
$('#CategoryDDL option:eq(0)').attr('selected', true);
$('#ButtonSearch').click(function (){ ButtonSearchEventHandler() });
});
ButtonSearchEventHandler()
這個function是在頁面上選擇產品分類後按下「List」Button所要執行的內容,
這裡所要做的事分別為:
- 取得分類的產品總數
- 顯示該分類第一個分頁資料以及使用並設定jQuery.pagination,以顯示Pager
function ButtonSearchEventHandler()
{
selected_Category_ID = $.trim($('#CategoryDDL option:selected').val());
selected_Category_Text = $.trim($('#CategoryDDL option:selected').text());
if (selected_Category_ID.length == 0)
{
alert('Please select a Category.');
return false;
}
else
{
//取得分類的產品總數
CategoryProductCount(selected_Category_ID);
var opt =
{
items_per_page: pageSize,
num_display_entries: 5,
prev_text: "上一頁",
next_text: "下一頁",
callback: PageSelectCallback
};
$("#Pagination").pagination(totalCount, opt);
}
}
在function中,設定使用jquery.pagination的方法第二個參數有去特別指定顯示上一頁、下一頁的文字。
CategoryProductCount()
這個funcion將會執行AJAX操作,將頁面上選擇的分類ID送回後端的「ProductCount」Action方法,以取得該分類下的產品總數,
這個操作只會在每個分類被選擇後執行一次,並不會在每次執行分頁時去執行。
function CategoryProductCount(categoryId)
{
var count = 0;
if (categoryId.length == 0)
{
return count;
}
else
{
$.ajax({
url: '@Url.Action("ProductCount", "Home")',
data: { categoryId: categoryId },
type: 'post',
async: false,
cache: false,
dataType: 'json',
success: function (data)
{
if (!data.Msg)
{
count = parseInt(data.count, 10);
totalCount = count;
}
}
});
}
return false;
}
PageSelectCallback()
function PageSelectCallback(page_index, jq)
{
GetCategoryProducts(page_index + 1);
return false;
}
這個就是jquery.pagination()方法中所指定的callback要執行的function,
在選擇產品分類下拉選單並且按下「List」Button後,就會執行第一個分頁資料的取得與顯示,
而這個callback方法所要接收的參數必須為:page_index以及jq,
page_index,這個是要顯示的分頁索引值,從零開始算,因為我後端取得分頁的PageIndex是從一開始算,所以這邊就做了「+1」的動作。
而「jq」這個則是指定Pager顯示容器的內容,看以下的圖示會比較清楚,
GetCategoryProducts()
這個function就是這一次主題的重心所在,
function GetCategoryProducts(pageIndex)
{
if (selected_Category_ID.length == 0 || selected_Category_Text.length == 0)
{
alert('Please select a Category.');
return false;
}
else
{
if ($.trim($('#CategoryDDL option:selected').val()) != selected_Category_ID.toString())
{
$('#CategoryDDL option[value=' + selected_Category_ID + ']').attr('selected', true);
}
$.ajax(
{
url: '@Url.Action("PageContent", "Home")',
data: { page: pageIndex, categoryId: parseInt(selected_Category_ID, 10) },
type: 'post',
async: false,
cache: false,
dataType: 'json',
success: function (data)
{
$('#table1 tbody').empty();
$('#CategoryName').empty();
$('#ProductNumber').empty();
if (data.Msg)
{
$('#Information').hide();
alert(data.Msg);
}
else
{
$.each(data, function (i)
{
var item =
{
ProductID: data[i]["ProductID"],
ProductName: data[i]["ProProductNameductID"],
SupplierID: data[i]["SupplierID"],
CategoryID: data[i]["CategoryID"],
QuantityPerUnit: data[i]["QuantityPerUnit"],
UnitPrice: data[i]["UnitPrice"],
UnitsInStock: data[i]["UnitsInStock"],
UnitsOnOrder: data[i]["UnitsOnOrder"],
ReorderLevel: data[i]["ReorderLevel"],
Discontinued: data[i]["Discontinued"]
};
$('#table1 tbody').append($('#TemplateProduct').tmpl(item));
});
$('#table1 tbody tr:odd').css('background-color', '#F5FBFC')
$('#ProductNumber').html(totalCount);
$('#CategoryName').html(selected_Category_Text);
$('#Information').show();
}
return false;
}
});
}
}
其實說穿了,這個方法與上一篇文章「ASP.NET MVC 3 資料套用範本 - 使用jQuery.Templates」中使用jQuery.Templates取得分類產品資料並且顯示的JavaScrtipt程式是相同的,
不同的地方在於,這個function要傳到後端「PageContent」Action方法的參數多了一個「page」,以取得指定的分頁資料。
大致上的程式內容就如上所示,不過要記得在View的頁面中要加入引用jquery.pagination的JS與CSS檔案,
<link href="@Url.Content("~/Content/pagination.css")" rel="stylesheet" type="text/css" />
<script src="@Url.Content("~/Scripts/jquery.pagination.js")" type="text/javascript"></script>
那我們就再一次看看這個分頁功能的操作畫面,這一次也來觀察每次網路傳送與接收的情況,
這一次介紹了在ASP.NET MVC 3下如何使用jQuery.Templates與jQuery Pagination Plugin來完成分頁的功能,
其實要完成分頁功能需求的方式有很多種,這邊使用了一個比較簡單的方式來完成,雖然說簡單,但也蠻實用的,
下次一樣也是會說明有關ASP.NET MVC 3 + jQuery Templates的方頁,
不過Pager將會搭配使用之前所設計「MvcSimplePostPager」,
既然之前都已經完成了 MvcSimplePostPager 的HtmlHelper,也用來搭配jQuery.Templates試試看吧!
以上
沒有留言:
張貼留言