close

引用網址:http://www.misterngan.com/1130/jqgrid-%E5%AF%A6%E7%94%A8%E6%8A%80%E5%B7%A7-%E5%8D%81%E4%B8%80-inline-edit-%E5%8F%8A-confirm-dialog-before-save/

所 有 強 橫 的 grid,都 必 須 要 支 援 inline editing 或 者 cell editing 的 ,jqgrid 當 然 也 不 例 外 。但 相 比 起 form editing,jqgrid 的 documentation 和 demo 網 站 都 比 較 簡 單 ,有 點 不 足 。

今 次 筆 者 就 為 大 家 介 紹 一 個 inline editing 的 例 子 吧 。

inline editing 如 何 控 制 那 一 個 column 能 修 改 呢 ?大 家 都 應 該 知 道 了 ,就 是 colModel 裡 面 的 editable。這 次 的 範 例 就 簡 單 一 點 ,只 有 一 個 欄 位 可 以 修 改 。

...
$("#list1").jqGrid({
....
colModel :[
....
{name:'prizeid',index:'prizeid',editable:true,edittype:'select',editoptions:{value:'0:---;1:Prize A;2:Prize B'}, formatter:'select',  },
....
],
...

inline editing 跟 cell editing 不 同 ,jqgrid 裡 面 是 沒 有 一 個 inlineEidt: true 的 選 項 的 。inline editing 一 切 的 控 制 都 在 幾 個 method:editRow、saveRow、restoreRow、addRow。

很 多 朋 友 誤 以 為 inline editing 欠 缺 form editing 的 眾 多 event 或 者 callback function,其 實 只 是 他 們 沒 有 在 設 定 好 以 上 method 的 parameters 而 已 。

一 般 來 說 ,inline editing 最 多 是 在 點 選 一 個 row 時 發 生 ,所 以 我 們 會 在 jqGrid 的 onSelectRow 事 件 加 入 。但 當 然 也 可 以 在 任 何 其 他 事 件 上 觸 發 。如 果 是 使 用 onSelectRow 事 件 ,我 們 多 數 不 希 望 使 用 者 一 次 修 改 多 於 一 筆 資 料 ,所 以 在 jqGrid 入 面 的 範 例 就 會 加 入 一 個 變 數 lastsel2 來 代 表 上 一 次 點 選 的 記 錄 ,這 個 要 預 先 宣 告 好 。

...
onSelectRow: function(id){
 if(id && id!==lastsel2){
  jQuery('#list1').jqGrid('restoreRow',lastsel2);
  jQuery('#list1').jqGrid('editRow',id);
  lastsel2=id;
 }
},
...

上 面 是 就 是 jqGrid demo 網 站 的 範 例 ,意 思 就 當 使 用 點 選 新 的 一 筆 記 錄 ,要 先 restore 之 前 點 選 的 記 錄 ,再 行 開 始 edit 現 在 新 點 選 的 記 錄 。但 裡 面 是 缺 少 了 一 些 很 有 用 的 parameters 的 。如 果 補 回 參 數 就 會 像 是 下 面 的 樣 子 。

...
var lastsel2;
$("#list1").jqGrid({
....
colModel :[
....
{name:'prizeid',index:'prizeid',editable:true,edittype:'select',editoptions:{value:'0:---;1:Prize A;2:Priz B'}, formatter:'select',  },
....
],
....
onSelectRow: function(id){
 if(id && id!==lastsel2){
  jQuery('#list1').jqGrid('restoreRow',lastsel2);
  var editparameters = {
   "keys" : true,
   "oneditfunc" : null,
   "successfunc" : null,
   "url" : "save_data.php",
   "extraparam" : {},
   "aftersavefunc" : reloadGrid,
   "errorfunc": null,
   "afterrestorefunc" : null,
   "restoreAfterError" : true,
   "mtype" : "POST"
  };
  jQuery('#list1').jqGrid('editRow',id,editparameters);
  lastsel2=id;
 }
},
...

在 上 例 中 ,大 部 分 的 參 數 都 是 預 設 值 ,其 實 如 果 你 使 用 預 設 值 的 話 是 不 用 加 進 去 的 。筆 者 修 改 了 是 keys、url 和 aftersavefunc。keys 預 設 是 false。如 果 改 成 true 的 話 ,你 就 可 以 在 修 改 的 時 候 按 Esc 來 restore,按 Enter 來 save,這 是 很 方 便 和 直 觀 的 。

url 就 是 post data 的 目 的 地 ,如 果 沒 有 設 定 ,jqgrid 就 會 使 用 editurl。

aftersavefunc 就 是 form editing 的 afterSubmit 事 件 。筆 者 在 這 裡 加 入 了 一 條 自 定 義 的 function reloadGrid,其 實 裡 面 也 做 沒 什 麼 ,就 只 是 reload 一 次 grid 而 已 。但 你 寫 的 時 候 ,就 可 以 按 需 要 而 做 任 何 事 情 了 。

那 如 果 不 是 每 一 筆 資 料 都 容 許 使 用 者 修 改 呢 ?inline editing 也 可 以 按 照 需 要 而 觸 發 的 。例 如 筆 者 舉 的 例 子 ,prizeid=0 就 是 未 選 擇 任 何 禮 品 ,prizeid=1 就 選 擇 了 prize A,如 此 類 推 。但 如 果 筆 者 想 每 筆 資 料 只 可 以 選 擇 一 次 禮 品 呢 ?就 是 說 ,如 果 選 好 了 禮 品 ,就 不 能 再 選 擇 了 ,這 如 何 做 呢 ?只 要 在 觸 發 editRow 之 前 檢 查 一 次 prizeid 就 可 以 了 。

...
var lastsel2;
$("#list1").jqGrid({
....
colModel :[
....
{name:'prizeid',index:'prizeid',editable:true,edittype:'select',editoptions:{value:'0:---;1:Prize A;2:Priz B'}, formatter:'select',  },
....
],
....
onSelectRow: function(id){
 var prizeID = $('#list1').jqGrid('getCell',id,'prizeid');
 if ( prizeID == 0 ) {
  if(id && id!==lastsel2){
   jQuery('#list1').jqGrid('restoreRow',lastsel2);
   var editparameters = {
    "keys" : true,
    "url" : "save_data.php",
    "aftersavefunc" : reloadGrid,
   };
   jQuery('#list1').jqGrid('editRow',id,editparameters);
   lastsel2=id;
  }
 }
},
...

當 使 用 點 選 一 行 的 時 候 ,我 們 檢 查 prizeid 的 值 ,如 果 是 零 的 話 ,我 們 才 觸 發 editRow 方 法 。這 樣 的 話 ,使 用 者 就 不 能 再 修 改 已 經 選 好 了 禮 品 的 資 料 行 了 。

inline editing 不 比 form editing,使 用 者 有 時 隨 便 點 選 一 行 就 開 始 edit 了 ,再 胡 亂 按 了 一 下 Enter,資 料 就 儲 存 入 資 料 庫 了 ,好 像 很 不 安 全 的 樣 子 。那 可 不 可 以 在 saveRow 之 前 給 一 個 confirm dialog 呢 ?很 多 朋 友 都 在 這 裡 觸 礁 了 ,他 們 會 想 找 一 個 beforeSave / beforeSubmit 的 事 件 ,可 惜 在 editRow 裡 面 是 沒 有 的 。相 反 的 ,其 實 我 們 應 該 主 動 拿 回 keypress 的 控 制 權 ,讓 我 們 自 己 選 擇 使 用 者 按 Enter 又 或 者 Esc 的 時 候 程 式 要 做 什 麼 。這 時 候 必 須 要 記 得 把 keys 設 定 為 false (false 是 預 設 值 )。

我 們 要 在 grid 裡 面 每 一 個 input 都 加 入 keypress event 控 制 ,最 方 便 的 莫 過 於 使 用 jquery 的 delegate 方 法 了 。delegate 不 只 可 以 綁 定 已 有 的 控 制 項 ,還 可 以 綁 定 將 來 新 增 的 控 制 項 (因 為 在 grid 裡 面 是 可 以 addRow 的 )。

筆 者 的 例 子 中 只 有 一 個 select 作 為 使 用 者 輸 入 的 控 制 項 ,所 以 delegate 就 會 如 下 。

...
var lastsel2;
...
$("#list1").jqGrid({
....
colModel :[
....
{name:'prizeid',index:'prizeid',editable:true,edittype:'select',editoptions:{value:'0:---;1:Prize A;2:Priz B'}, formatter:'select',  },
....
],
....
onSelectRow: function(id){
 var prizeID = $('#list1').jqGrid('getCell',id,'prizeid');
 if ( prizeID == 0 ) {
  if(id && id!==lastsel2){
   jQuery('#list1').jqGrid('restoreRow',lastsel2);
   jQuery('#list1').jqGrid('editRow',id);
   lastsel2=id;
  }
 }
},
.....
});
...
...
$('#list1').delegate('select.editable','keypress', function(e) {

 var code = (e.keyCode ? e.keyCode : e.which);

 if(code == 13) { //Enter keycode
  var currentID = $(this).attr("id");
  currentID = currentID.replace('_prizeid','');
  $("#confirm_dialog").dialog({
    modal: true,
    buttons: {
     'Ok': function() {
      var saveparameters = {
       "url" : "save_data.php",
       "aftersavefunc" : reloadGrid,
      };
      $('#list1').jqGrid('saveRow',currentID,saveparameters);
      $( this ).dialog( "close" );
     },
     'Cancel': function() {
      $('#list1').restoreRow(currentID);
      lastsel2=-1;
      $( this ).dialog( "close" );
     }
    }
   });
 }

 if(code == 27) { //Esc keycode
  var currentID = $(this).attr("id");
  currentID = currentID.replace('_prizeid','');
  $('#list1').restoreRow(currentID);
  lastsel2=-1;
 }
)};
...

那 個 confirm_dialog 筆 者 就 不 寫 出 來 了 ,不 就 是 一 句 Are you Sure 之 類 的 。上 例 中 比 較 不 好 理 解 的 是 如 何 取 得 saveRow 裡 面 需 要 的 row id。其 實 這 個 row id 就 已 經 存 在 於 每 一 個 由 jqgrid 自 動 生 成 的 input control 裡 面 。例 如 row id 是 50,那 麼 這 個 控 制 項 自 己 的 id 就 會 是 50_name,這 個 name 就 是 colModel 裡 面 的 name 參 數 。由 於 我 的 colModel 裡 面 的 name 是 prizeid,所 以 控 制 項 的 id 就 是 50_prizeid 了 。

要 由 這 個 控 制 項 的 id 取 得 row id,只 要 移 除 後 面 的 _prizeid 就 可 以 了 。row id 的 字 數 長 度 是 不 固 定 的 ,所 以 還 是 用 replace 比 較 好 ,而 不 能 用 substring。

當 你 取 得 row id (上 例 的 變 數 就 是 currentID),其 餘 一 切 也 好 辦 ,想 要 save 就 用 saveRow method,想 要 取 消 就 用 restoreRow method。在 上 例 中 ,如 果 使 用 按 了 Enter,就 彈 出 來 confirm_dialog,如 果 使 用 選 OK 就 save,如 果 選 Cancel 就 restore。另 外 ,如 果 在 編 輯 中 途 按 了 Esc,也 同 樣 是 restore。

當 restoreRow 方 法 之 後 ,記 得 也 要 把 那 個 lastsel2 變 數 回 復 一 下 ,不 然 的 話 ,你 restoreRow 之 後 ,想 要 再 點 選 回 同 一 行 來 修 改 就 會 無 反 應 的 了 。在 上 例 我 把 lastsel2 設 定 為 一 個 不 存 在 的 -1 。

然 後 在 onSelectRow 當 中 ,因 為 儲 存 的 動 作 改 為 由 SaveRow 去 處 理 ,所 以 editRow 的 參 數 就 全 部 使 用 預 設 值 就 可 以 了 ,但 記 得 keys 必 須 要 是 false (false 是 預 設 值 ),這 別 搞 錯 了 。然 後 ,本 來 的 url 和 aftersavefunc,就 都 搬 到 saveRow 作 為 參 數 。

就 這 樣 ,一 個 confirm dialog before save 就 完 成 了 。呵 呵 。

arrow
arrow
    文章標籤
    jquery jqGrid
    全站熱搜

    龍之家族 發表在 痞客邦 留言(0) 人氣()