AJAX後台網站的最後一塊拼圖 Flexigrid (1)
假如說後台網站是要提供使用者去新增修改刪除一張Table
那前面講的東西都只是針對其中一筆資料
拿ASP.NET的控制項來說, 基本上就只是DetailView ( 還是FormView ? 幾乎沒用過忘記了 orz )
可是我們缺少最重要的東西, 也就是GridView
我們一定需要一個可以展示所有資料的機制, 讓使用者可以一目了然看到資料
並且很輕鬆的選擇他要操作哪一筆資料
而這邊提供一個AJAX的Solution : Flexigrid
他是一個很優秀的輕量級 jQuery Table UI, 可以很簡單的跟ASP.NET配合做出一個動態表格
官方網站為 : http://www.flexigrid.info/
上面如此介紹此套ui
Features
- Resizable columns
- Resizable height and width
- Sortable column headers
- Cool theme
- Can convert an ordinary table
- Ability to connect to an ajax data source (XML and JSON[new])
- Paging
- Show/hide columns
- Toolbar (new)
- Search (new)
- Accessible API
- Many more
附上一張開發中專案的貼圖
可以看到他有很簡潔的畫面,
而我覺得他最值得稱道的, 是他提供非常直覺的操作, 例如說
1. 點選欄位標題, 可以對該欄位進行排序
2. 點上一頁下一頁的按鈕, 可以換頁
3. 輸入要搜尋的欄位以及內容, 可以自動篩選資料
4. 上方的按鈕很清楚的告訴了可以對目前選擇的資料有哪些操作
這樣當使用者第一次看到這頁, 其實不用特別的說明, 他也知道該怎麼用
而在畫面上看不出來的功能有
1. 可以任意拖曳欄位順序
2. 可以拖曳而輕鬆欄位的寬度
3. 可以選擇要顯示的欄位 ( 當欄位數量很多的時候 這三個屬性幫助非常的大)
最重要的, 這些東西都可以經由客製化的選項去調整或關閉啟用
接下來就是直接切入主題, 要怎麼去用它
=================================================================================================
一、他為什麼可以做到任意欄位排序、搜尋的功能
剛看到都會覺得很神奇, 為什麼區區一個小js UI, 就可以做到隨便點哪個欄位都可以排序, 隨便哪個欄位都可以提供搜尋
其實原理很簡單
因為他根本就沒有真的排序, flexigrid只是把使用者要排序的欄位丟到Server端
告訴我們: "現在使用者要用這個欄位 [Name] 排序, 趕快排好送過來"
然後我們的程式就默默的開始排序接著排序好之後丟回去Client端
至於分頁跟搜尋也是一樣的道理
不過也已經夠好用了, 畢竟比起GridView笨重的操作ViewState這個怪物
Flexigrid走 AJAX, 加上提供很友善的介面
使用者可以很輕鬆的操作, 然後用更快的速度取得表格的資料
其實Flexigrid的介紹去google不乏很值得參考的文章
因此這篇主要就是把重點擺在, Flexigrid如何透過PageMethod跟ASP.NET溝通
=================================================================================================
二、要怎麼宣告
先從Client端說起, flexigrid的宣告方式就跟其他jQuery的UI一樣
$('#table').flexigrid({
url: '{pageName}/GetTable', dataType: 'json',
colModel: [
{ display: "Name", name: "Name", width: 120, sortable: false, align: 'right' },
{ display: "Age", name: "Age", width: 40, sortable: true, align: 'left' }
],
buttons: [
{ name: 'Edit', bclass: 'edit', onpress: gridCmd },
{ separator: true },
{ name: 'Add', bclass: 'add', onpress: gridCmd },
{ name: 'Delete', bclass: 'delete', onpress: gridCmd },
{ separator: true }
],
searchitems: [
{ display: 'Name', name: 'Name' },
{ display: 'Age', name: 'Age' }
],
sortname: 'UserName', sortorder: 'asc', usepager: true, title: 'Student List', useRp: true, rp: 10,
showTableToggleBtn: true, showCheckbox: false, singleSelect: true, width: 800, height: 400
});
function gridCmd(cmd, grid) {
switch(cmd) {
case 'Add':
break;
case 'Edit':
case 'Delete':
var $tr = $('.trSelected', grid);
if ($tr.length == 0) {
alert('請先選擇資料!');
return;
}
var id = $tr.attr('id');
id = id.substring(id.lastIndexOf('row') + 3)
break;
}
}
其實這部分的資訊網路上已經非常多
僅簡單說明重要屬性如下
a. url – 輸入PageMethod的位置
b. dataType - 輸入'json' (以上這兩個還是為了要配合PageMethod而操作)
c. colModel - 要有哪些欄位, 他的顯示名稱是什麼(display), 他實際上對應資料表的欄位是什麼(name), 他是否可以排序(sortable), 跟其他屬性
d. searchitems - 要提供哪些欄位讓使用者可以搜尋, 以及顯示名稱跟欄位名稱
e. usepager - 是否要讓使用者能夠分業
f. singleSelect - 是否同時只能選一列
g. buttons - 要有哪些按鈕可以讓使用者操作, 按鈕名稱是什麼(name), 按鈕要套用什麼class(bclass) 像是剛剛demo畫面的按鈕圖片, 就是在這邊定義
h. gridCmd - 自定義的function, 按鈕點擊之後會觸發這個function, 我們可以根據cmd這個屬性判斷是哪個按鈕被點下去, 再做對應的處理
i. .trSelected - 在gridCmd中可以看到使用這個class取得被選擇的tr, .trSelected是flexigrid預設被選中的tr會帶的class
j. id - 每一列會帶一個id (之後傳資料的格式會講到), 而那個id會被寫成<tr id="row1" class="trSelected"> 像這種格式, 因此把他substring取得這一列的id
k. showCheckbox - 是否每一列的一開始要秀一個checkbox, 這是多選的進階應用, 可以在自行研究
至於其他屬性, 建議查其他網站或是官網, 會有更詳細的說明
=================================================================================================
三、必須要改程式
雖然我們希望這樣宣告之後就可以很順利的把值丟到Server端的PageMethod去處理
但是這flexigrid畢竟不是為了ASP.NET的PageMethod所開發, 有些地方已經被寫死
我們需要去配合修改程式才可以順利的傳資料,
可以打開官網下載的flexigrid.js
直接到 line 579, populate: function () { //get latest data
這個function是flexigrid去跟Server端要資料的function
A ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
首先先看到line 606
var param = [
{ name : 'page', value : p.newp }
,{ name : 'rp', value : p.rp }
,{ name : 'sortname', value : p.sortname}
,{ name : 'sortorder', value : p.sortorder }
,{ name : 'query', value : p.query}
,{ name : 'qtype', value : p.qtype}
];
可以看到原本他是用陣列的方式宣告他要傳給Server端的變數 ( 變數的意義下一篇再解釋 )
我們恢復他mark的資料
改為
var param = { page: p.newp, rp: p.rp, sortname: p.sortname, sortorder: p.sortorder, query: p.query, qtype: p.qtype };
為什麼要這麼改, 因為我們要把資料丟給PageMethod, 就用$.toJSON(obj)的老方法
B ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
接下來看到line 615
if (p.params)
{
for (var pi = 0; pi < p.params.length; pi++) param[param.length] = p.params[pi];
}
改為
if (p.params)
$.extend(param, p.params);
簡單來說這邊的差異是假如有額外的參數, 就把他加入物件當中, 若暫時用不到也可以直接MARK起來
C ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
接下來是
$.ajax({
type: p.method,
url: p.url,
data: param,
dataType: p.dataType,
success: function(data){g.addData(data);},
error: function(XMLHttpRequest, textStatus, errorThrown) { try { if (p.onError) p.onError(XMLHttpRequest, textStatus, errorThrown); } catch (e) {} }
});
改為
$.ajax({
type: p.method,
contentType: p.contentType,
url: p.url,
data: $.toJSON(param),
dataType: p.dataType,
success: function (data) { g.addData(data); },
error: function (XMLHttpRequest, textStatus, errorThrown) { try { if (p.onError) p.onError(XMLHttpRequest, textStatus, errorThrown); } catch (e) { } }
});
簡單來說, 補上contentType (JSON), 把data改成用$.toJSON
這樣就完成了修改, 可以用flexigrid直接把參數丟給PageMethod了
這邊感覺上很複雜, 不過這些努力都會是有代價的
D ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
我們看到success, flexigrid直接把data丟給了g.addData
這樣基本上是肯定錯的, 因為PageMethod丟回來的值, .NET會自動的多包一層d
data = {
d : {
//真正的物件
}
}
所以我們可以直接在這邊改成
$.ajax({
type: p.method,
contentType: p.contentType,
url: p.url,
data: $.toJSON(param),
dataType: p.dataType,
success: function (data) { g.addData(data.d); },
error: function (XMLHttpRequest, textStatus, errorThrown) { try { if (p.onError) p.onError(XMLHttpRequest, textStatus, errorThrown); } catch (e) { } }
});
不過不太建議這樣寫, 因為這樣等於把程式給寫死了, 假如有其他來源的資料要進flexigrid, 那他沒有那層d不就死翹翹了
所以可以修改成
success: function(data) {
if (data.d) data = data.d;
g.addData(data);
}
當然也可以改在addData的地方
就看要怎麼發揮了
大致上第一部分先聊到這邊, 到這邊我們已經可以把flexigrid的異動後的參數正確的丟到Server端
下一篇則是Server端要怎麼接這些參數, 以及要回傳什麼格式給flexigrid的addData
--
本文可能有理解錯誤 或不盡不實的地方
請路過的前輩不要客氣 用力打醒
這會是我們成長的主要養分