AJAX後台網站的最後一塊拼圖 Flexigrid (1)

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

 

附上一張開發中專案的貼圖

flexigrid

 

可以看到他有很簡潔的畫面, 

 

而我覺得他最值得稱道的, 是他提供非常直覺的操作,  例如說

 

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

 

--

本文可能有理解錯誤  或不盡不實的地方

請路過的前輩不要客氣  用力打醒

這會是我們成長的主要養分