jqGrid 實用技巧 (十) 用 custom_func 檢查資料的唯一性

答 讀 者 Pippen :

很 多 時 候 ,在 資 料 表 的 數 據 ,隨 了 主 鍵 那 個 index number 之 外 ,有 很 多 其 他 的 field 我 們 也 會 設 定 成 唯 一 的 (Unique)。那 如 何 使 用 jqGrid 的 custom_func,在 插 入 資 料 之 前 去 檢 查 一 下 使 用 者 輸 入 的 資 料 在 之 前 是 不 是 已 經 出 現 過 呢 ?

我 自 己 的 習 慣 是 用 jQuery 的 ajax 來 做 。在 下 面 的 例 子 裡 ,我 有 一 個 field 是 rankname,是 用 來 儲 存 職 位 名 稱 的 。在 資 料 表 裡 面 已 經 有 rankcode 作 為 主 鍵 ,所 以 rankname 就 只 是 唯 一 鍵 。

...
colModel :[
....
{name:'rankname',index:'rankname',editable:true,edittype:'text',editoptions:{size:20,maxlength:20},editrules:{required:true,custom:true,custom_func:checkRank}},
....
],
...

在 checkRank 裡 面 ,我 用 jQuery.ajax 把 使 用 者 輸 入 的 資 料 傳 到 checkrankname.php 去 檢 查 ,再 按 它 傳 回 來 結 果 處 理 。

特 別 要 留 心 的 是 ,async 必 須 設 置 為 false,意 思 就 是 強 制 它 做 同 步 處 理 ,即 是 要 等 到 有 結 果 傳 回 ,程 式 才 會 繼 續 執 行 下 去 。大 概 有 很 多 朋 友 都 試 過 在 這 個 小 小 的 設 定 上 面 出 問 題 。

...
function checkRank(posdata, obj){
 var result = null;
 jQuery.ajax({
 async: false,   //this is crucial
 url: 'checkrankname.php',
 type: 'post',
 data: {rankname: posdata.rankname},
 dataType: 'json',
 success: function (data) {
  if (data.success) {
   result = [true, '']
  } else {
   result = [false,'職 位 名 稱 : ' + data.rankname + ' 已 使 用 '];
  }
 },
 error: function () { alert('Error trying to validate rankname ' + posdata.rankname); }
 });
 return result;
 }
...

至 於 那 個 php 檔 ,最 簡 單 的 大 概 就 是 像 下 面 的 樣 子 。

...
$rankname = $_POST['rankname'];

openConnection();
$strSQL = "SELECT rankname FROM rank_table WHERE rankname='$rankname' ";
$rankcheck = mysql_query($strSQL);
$rankcheck2 = mysql_num_rows($rankcheck);

if ($usercheck2 > 0) {
    $data['success'] = false;
    $data['rankname'] = $rankname;
} else {
    $data['success'] = true;
    $data['rankname'] = $rankname;
}

echo json_encode($data);
...

但 也 有 些 時 候 ,要 檢 查 唯 一 值 的 field 多 於 一 個 ,筆 者 也 會 把 custom function 放 在 beforeSubmit 裡 面 執 行 。在 第 二 個 例 子 ,我 們 有 branchcode 和 branchname,是 存 放 分 行 編 碼 和 分 行 名 稱 的 。

...
$("#list").jqGrid({
...
colModel :[
....
{name:'branchcode',index:'branchcode',editable:true,edittype:'text',editoptions:{size:20,maxlength:20},editrules:{required:true}},
{name:'branchname',index:'branchname',editable:true,edittype:'text',editoptions:{size:100,maxlength:100},editrules:{required:true}},
....
],
pager: '#pager',
...

但 這 次 我 們 不 用 custom_func,而 把 function 放 在 pager 裡 面 的 add 和 edit 裡 面 的 beforeSubmit。

...
$("#list").jqGrid('navGrid','#pager',
{edit:true,add:true,del:false,search:true,view:true},
{beforeSubmit:checkBranch},
{beforeSubmit:checkBranch},
{},
{},
{}
);
...

至 於 那 條 function 也 大 同 小 異 。

...
 function checkBranch(posdata, obj){
  var result = null;
  jQuery.ajax({
  async: false,   //this is crucial
  url: 'checkbranch.php',
  type: 'post',
  data: {branchname: posdata.branchname, branchcode: posdata.branchcode},
  dataType: 'json',
  success: function (data) {
   if (data.success==0) {
   result = [true, '']
   } else if (data.success==1) {
   result = [false,'分 行 名 稱 : ' + data.branchname + ' 已 使 用 '];
   } else if (data.success==2) {
   result = [false,'分 行 編 碼 : ' + data.branchcode + ' 已 使 用 '];
   }
  },
  error: function () { alert('Error trying to validate branch name'); }
  });
  return result;
 }
...

因 為 一 次 過 檢 查 多 於 一 個 field,所 以 傳 回 的 success 變 數 就 由 true / false 變 為 0 / 1 / 2 三 個 可 能 性 了 。

ctleung張 先 生 ,男 性 ,肖 龍 。
職 業 :I.T. Consultant
簡 介 :不 好 好 讀 書 ;七 尺 差 五 寸 ,手 長 過 膝 ,雙 耳 垂 肩 ;性 寬 和 ,寡 言 語 ,喜 怒 不 形 於 色 。據 說 少 時 曾 斬 白 蛇 於 鳳 凰 山 下 ……
This entry was posted in jqGrid and tagged , , , , . Bookmark the permalink.

10 Responses to jqGrid 實用技巧 (十) 用 custom_func 檢查資料的唯一性

  1. Pippen says:

    非常感谢!而且使用了两种不同的入口来判断。
    关于jaon返回的数据格式, 曾经在ajax 的if(data.success)的判断的时候, 无论如何也没有得到false的返回值, 后来才发现是因为返回的数据值的真与假是要使用布尔值的,也就是说返回的要是true和false不是字符串的“ture”和“false”。
    比如我的返回json格式就是:
    {
    “check_column”:”column_name”,”check_value”:” input_value”,”unique_flag”:true
    }
    这里的“unique_flag”的对应的值是布尔值ture, 不是字符串”true”, 提醒大家注意。

    • C.T. Leung says:

      其實用 string 也可以的,只不過你的判斷式要改成 if (data.success==’true’)。我們用if (data.success) 比較多,是因為這種寫法比較簡潔一點吧。

  2. tony says:

    承蒙先前指導, 有漸入佳境了,
    現在有個 動態 editoptions 的問題請教,
    例如 縣市 , 鄉鎮的輸入
    縣市-> 選了台北市, 那 鄉鎮就只剩台北的區可以選,
    edittype = select
    習慣用 formedit, 不曉得 lineedit 是否一樣,
    謝謝 賜教..

    • C.T. Leung says:

      是的,當然是一樣的。

      只不過 form edit 那張 form 裡面只有一個「鄉鎮 select」,而 inline edit 則是一整個 page 那麼多的「鄉鎮 select」。只要你搞清楚每個「鄉鎮 select」的 id 就可以了,操作上是完全沒有分別的。

  3. tony says:

    不好意思, 我主要不是問 form edit 和 inline edit 的差異,
    是要問 動態 editoptions 的做法,
    參照 google 的一些做法, 沒辦法完成, 光是 editoptions:{value:xxxx}
    有 function xxxx(){}
    jqgrid 就顯示不出來了,
    主選項(如:縣市) 還ok, 是固定項目
    次選項(如:鄉鎮) 比較有問題, 如何帶入 主選項的值, 來動態產生 相對應的選單
    謝謝!!
    請再次指教…

    • C.T. Leung says:

      還真看不出,你是問這個。我再三拜讀了你之前的留言,實在完全看不出你不會寫…..

      首先,你那個所謂 Google 出來的做法,筆者很有保留。你應當問問自己,你希望你的程序是在什麼樣的情況下觸發呢?如果是用 editoptions:{value:function_name} 這樣的寫法,它只會在生成表格的時候執行,又怎麼能夠在你選完「主選項」的時候去改變「次選項」呢?

      [題外話,你 jqgrid 不能顯示出來,大概是因為 function xxxx 傳回的東西不對吧,你可以獨立檢查一下 function xxxx 傳回了什麼]

      假如你是希望使用者選完「主選項」,而觸發「次選項」內容的改變,你得問問自己要用那一個 event?

      直觀的,我們當然首先想到 jquery 的 .change() event 吧。

      $("#1st_select_id").change(function(){
      // do something to change the 2nd select
      });

      這個做法是絕對可以的,亦是最常見、最正宗的做法。

      但其實 jqGrid 裡面亦有一個 event,用起來可能會方便一些。

      就是 editrules:{custom:true, custom_func:change2ndselect}。如果你有看過我的文,就知道這是用 custom function 做 data validation 的寫法。它觸發的時間剛好就是使用者輸入完「主選項」的時候。

      function change2ndselect(value,colname){
      // change 2nd select according to value of 1st select
      return [true,""];
      }

      用這個方法的時候,千萬別忘記了一樣要傳回 true 呀。它就是告訴 jqGrid 你的 data validation 沒問題的意思。

      多得同業來信指正,jqGrid 的 data validation 只會在 form submit 的時候觸發,而不會在每個 form field 輸入完成的時候觸發。

      • tony says:

        再請教:
        如何設定 或 取得 主選項的 id, 來做 change 的動作?
        及 以 ajax 取得 次選項 的內容後, 次選項 應以何種方式 接收…
        謝謝!!

      • tony says:

        知道 change 或 click 了
        在 editoptions 內 加上
        dataEvents: [ { type: ‘change’, fn: function (e) {…… } }]
        即可,
        還在試如何傳給 次選項…
        謝謝!!

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>