jqGrid 實用技巧 (五) Form Edit

[anti-both]

好 不 容 易 ,終 於 寫 到 jqGrid 的 Form Edit。我 們 再 一 次 回 到 功 能 強 大 的 colModel。

1
2
3
4
5
6
7
...
colModel :[
   ....
   {name:'name',index:'name',editable:true,edittype:'text',editoptions:{size:50,maxlength:100},editrules:{required:true}},
   ....
],
...

在 colModel 裡 面 ,跟 Form Edit 有 直 接 關 係 的 参 數 有 4 個 – editable、edittype、editoption 和 editrules。

editable,顧 名 思 義 ,就 是 設 定 這 個 欄 位 能 不 能 修 改 。預 設 值 是 false。如 果 是 editable:flase 的 話 ,該 欄 位 是 不 會 出 現 在 Edit Form 裡 面 的 。

edittype,就 是 Edit Form 裡 面 的 <input> Tag 的 種 類 。edittype 的 值 可 以 是  text,textarea,select,checkbox,password,button,image,file 和 custom。就 是 相 應 的 ,<input type=text>,<textarea></textarea>,<select></select> 等 等 在 表 單 裡 面 使 用 的 輸 入 項 。

editoptions,就 是 <input> Tag 裡 面 ,額 外 的  attributes。這 些 attributes 會 跟 據 edittype 而 有 所 不 同 。例 如 上 面 的 例 子 ,edittype 是 text,所 以 就 相 應 的 加 入 size 和 maxlength 參 數 。再 看 下 面 的 另 一 例 。

1
2
3
4
5
6
7
...
colModel :[
   ....
   {name:'description',index:'description',editable:true,edittype:'textarea',editoptions:{rows:"5",cols:"50"},editrules:{required:true}},
   ....
],
...

由 於 edittype 是 textarea,所 以 size 和 maxlenght 都 不 會 生 效 。於 是 我 們 相 應 的 加 入 rows 和 cols 這 兩 個 textarea 相 關 的 參 數 。editoptions 也 是 設 定 select 的 option 的 地 方 。

1
2
3
4
5
6
7
...
colModel :[
   ....
   {name:'enable',index:'enable',editable:true,edittype:'select',editoptions:{value:"0:正 常 ;1:停 用 "}},
   ....
],
...

另 外 ,editoptions 也 可 以 使 用 dataInit function(就 像 searchoptions 一 樣 ), 加 入 jQuery UI。在 下 例 中 我 就 使 用 了 jQuery UI 的 datepicker。

1
2
3
4
5
6
7
8
9
10
11
12
13
...
colModel :[
   ....
   {name:'date',index:'date',editable:true,edittype:'text',editoptions:{dataInit:datePick,size:10,maxlength:10},editrules:{required:true,date:true}},
   ....
],
...
...
...
function datePick(elem){
   $(elem).datepicker({ dateFormat: "yy-mm-dd" });
}
...

至 於 最 後 的 editrules,就 是 做 data validation 的 。jqGrid 本 身 已 經 包 含 了 很 多 常 用 的 data validation,令 開 發 者 節 省 了 很 多 時 間 。例 如 上 例 的 的 editrules:{required:true,date:true},意 思 就 是 「不 得 留 空 」和 「必 須 是 日 期 」。jqGrid 的 editrules 還 有  number,integer,minValue,maxValue,email,url,time,custom。

Data Validation

而 其 中 的 custom ,就 是 讓 開 發 者 在 jqGrid 本 來 的 data validation 不 夠 用 的 時 候 ,可 以 簡 易 的 新 增 自 定 義 的 data validation。請 看 下 例 。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
...
colModel :[
   ....
   {name:'pass',index:'pass',editable:true,edittype:"password",editrules:{required:true,custom:true, custom_func:checkPassword}},
   ....
],
...
...
function checkPassword(value, colname) {
   if (value.length < 8)
      return [false, "Password too short"];
   else
      return [true, ""];
}
...

這 是 一 個 使 用 者 密 碼 的 欄 位 ,筆 者 希 望 使 用 者 輸 入 的 密 碼 至 少 要 有 8 個 位 。首 先 ,我 們 在 editrules 加 入 custom:true,然 後 再 加 入 一 條 自 定 義 的 function,custom_func: checkPassword。自 定 義 function 的 參 數 value,就 是 使 用 者 輸 入 的 數 值 了 。value.length 就 是 value 字 串 的 長 度 ,少 於 8 的 話 ,我 們 就 傳 回 false,以 及 錯 誤 訊 息 ,這 個 錯 誤 訊 息 是 會 在 Edit Form 上 面 顯 示 給 使 用 者 的 。如 果 檢 查 之 後 是 正 確 的 話 ,就 傳 回 true。

Password too short

好 了 ,現 在 Form View,Form Edit,Form Search 我 們 都 獨 立 的 學 了 一 遍 。下 一 回 ,我 們 就 試 作 一 些 複 雜 一 點 的 欄 位 ,看 看 同 一 個 欄 位 的 colModel 在 夾 雜 了 View ,Edit,Search 等 等 之 後 會 變 成 什 麼 樣 子 。

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

This entry was posted in jqGrid and tagged , , , , , , , , . Bookmark the permalink.

30 Responses to jqGrid 實用技巧 (五) Form Edit

  1. Pippen says:

    你好, 看了你写的jqgrid的文章,有个问题想请教一下。
    我的数据列有一个唯一性约束,unique constraint。比如用户名注册的时候不能重复。
    如何在添加数据的时候验证用户名的唯一性呢?
    我想到的是使用自定义的custom_func来验证,但是并不知道具体怎么来验证。
    比如修改用户名的时候,也需要验证用户名是否已经存在。

    谢谢。

  2. tony says:

    請問一下:
    用form edit 修改資料後, 按submit,會進行存檔, 但是form edit的畫面依然存在,
    請問要如何在按submit後, 該form會關閉,
    謝謝!!

    • C.T. Leung says:

      這個很簡單。在 form editing 裡面有兩個 Properties: closeAfterAdd 和 closeAfterEdit。兩者的預設值都是 false。

      預設值是方便使用者一次過新增多筆資料,又或者修改多筆資料 [ edit 的時候可以用前後箭號移動到不同的 record ]。

      這個你只要在 pager 裡面修改就可以了。

      1
      2
      3
      4
      5
      6
      
      $("#list").jqGrid('navGrid','#pager',
        {edit:true,add:true,del:false,search:false,view:false},
        {closeAfterEdit:true},
        {closeAfterAdd:true},
        ....
      });
      • homer says:

        以下是我的 code 請教一下 我可以edit 且資料也會修改的資料庫 但是 就是無法 closeAfterEdit 及 reloadAfterSubmit 可以協助一下嗎?

        jQuery(“#jqGrid”).jqGrid(‘navGrid’,’#jqGridPager’,{
        afterSubmit: function (response, postdata) {
        Resp = JSON.parse(response.responseText);
        if (Resp = Resp.success) {
        return [true,”ok”,Resp.newid];
        } else {
        return [false,Resp.err];

        }
        },
        view:true,search:true,addtext:’Add’,edittext: ‘Edit’,deltext: ‘Delete’,refreshtext:’Reload’,
        reloadAfterSubmit:’true’,
        closeAfterAdd:’true’,
        closeAfterEdit:’true’
        });

        • C.T. Leung says:

          http://www.trirand.com/jqgridwiki/doku.php?id=wiki:navigator

          根據 jqGrid 的 documentation,Navigator 的用法如下:

          jQuery(“#grid_id”).jqGrid(‘navGrid’,’#gridpager’,{parameters},prmEdit, prmAdd, prmDel, prmSearch, prmView);

          Where:

          grid_id – the id of the already constructed jqGrid.
          gridpager – the id of the navigation bar
          parameters – an array of settings, defined below
          prmEdit, prmAdd, prmDel, prmSearch, prmView are objects which holds the parameters and events for a particular action in Form editing

          我再怎麼看你的 code,也不是跟隨 documentation 的格式寫的呀,咁唔 work 就一定架啦 ……

          我理解寫程式就好似寫小說一樣,你是作者,天馬行空,天下任我縱橫,你想點寫都得。但前題係,唔好用人地已經開發好既工具。用得人地的工具,就最好跟返人地 documentation 的寫法去寫程式。Documentation 的網址我上面 post 左出黎,你自己慢慢睇。謝謝。

  3. tony says:

    又來請教了,
    請問一下, 我是用 form edit
    若欄位有 數量 . 單價 . 小計
    在 數量 及 單價 change Event 去計算 小計
    到這裡都 ok,
    再來要把 小計的數字 放入 “小計” 就不會了,
    上次 select 的動態選項 是以
    $(“#tr_field select.FormElement”).html(msg);
    的方式, 試了很多種方式, 依然無法
    所以…..
    如果 inline edit 不一樣作法, 也請一併賜教
    謝謝!!

    • C.T. Leung says:

      你能算出「小計」的值,但不會把它放到「小計」的 element 裡面,但怎麼「小計」會是用 select??不太可能吧….

      如果你真係有獨立的不同問題,你可以分開一題一題來問麼?例如:
      1. xxxxxx
      2. xxxxxx
      3. xxxxxx

      • tony says:

        sorry, 我是說上次動態 select 是用
        $(“#tr_field select.FormElement”).html(msg);
        的方式完成, 不是小計要用 select…
        而這次 的問題是要 塞 小計的值,
        我想 作法應該相當, 只是不知道 keyword為何…
        遵照指示:
        1. 在 form edit 中,如何將 100 塞給 total 的欄位?
        2. inline edit 方法一樣嗎?
        謝謝!!

        • C.T. Leung says:

          如果用最常見的 text input 來做例子。

          form editing

          form editing 的話,input 的 id 就是 colModel 裡面的 name。在我的例子中,colModel 的 name 是 remarks,所以 input 的 id 也就一樣是 remarks。

          所以寫法就是:
          $(‘#remarks’).val(subtotal);

          row editing

          至於 row editing 的話,input 的 id 就是 row id 再加上 colModel 裡面的 name。例子中 name 是 invdate,而該行的 row id 是 13,所以加起來就是 13_invdate。

          寫法也是完全一樣:
          $(‘#13_invdate’).val(subtotal);

          我個人覺得重點有兩個吧。

          第一,看來你要用一點點時間來學學 jquery。或許你不知道,但整個 jqGrid 都是用 jquery 寫出來的,沒有 jquery 就不會有 jqGrid。所以 jquery 是鐵定要學的。用 .val() 來設定 input 的值,正是基本中的基本,正常情況是不可能不知道的。而用什麼 id (或是其它方法) 來選取一個 element,更是 jquery 的重中之重。不搞清楚這些東西,jqGrid 是不會用得好的。

          第二,就是在上例中,在 row editing 要如何取得 row id ( 並且把它和 column name 組合成你要的 element id )。不過這亦是 jqGrid 一個十分基本的操作,我就不在此累贅了。

  4. tony says:

    你們真棒,
    .val() 這我知道,
    原先以為 jqgrid 設的 id , 可能會加上某些前碼,
    所以沒有以 name 來試, 東猜西猜…..
    沒想到就是 直接 以 name 為 id,
    不過也多了解了 row_id+_+name 是 inline edit 的 id
    真是受教….
    謝謝!!

  5. gavin says:

    請問,我在edit form或add form畫面時,因欄位多,有只打到一半,滑鼠不小心點了edit form以外的地方,整個edit form就不見了,前面打的字也不見了。
    是否有可以edit form,不會因這樣的情況而消失呢?

    • C.T. Leung says:

      其實這個在 jqGrid 的 documentation 就有講。你需要的是 jqModal plugin 和 jqGrid 的兩個設定。

      1. jqModal plugin :
      http://jquery.iceburg.net/jqModal/
      下載之後當然就是引用啦。
      <script type="text/javascript" src="jqModal.js">

      2. jqGrid 的兩個設定 :
      jqModal:true,
      modal:true,
      它們要放在 form editing 的設定裡面,而不是 jqGrid 的設定裡面。而每一張 Form (add,edit,search,view) 的 modal 都是可以獨立設定的。
      $("#list").jqGrid('navGrid','#pager',
      {edit:true,add:true,del:false,search:true, view:true},
      {jqModal:true,modal:true}, //edit
      {jqModal:true,modal:true}, //add
      {}, //del
      {jqModal:true,modal:true}, //search
      {jqModal:true,modal:true} //view
      );

      設定了 modal 之後,Form 就不會因為你點選了外面的空白地方而 close 的了 ( 一定要 click “close” / “cancel” button 才會 close )。剛好見到網上有一個現成的 example ( 不是我做的!! ),也給你參考吧:
      http://www.ok-soft-gmbh.com/jqGrid/LocalFormEditing.htm

      • tony says:

        日前jqModal有更新, 若下載新版, 就不能用了…
        所以舊的可別丟了

        • C.T. Leung says:

          老兄, 可唔可以詳細些少?例如乜野版本(jqModal)同乜野版本(jqgrid/jquery)唔夾呀?新版講既係幾新?舊版講既又係幾舊呀?謝謝。

  6. janice says:

    若按了編輯後,需要執行一組後端程式產生資料,然後將資料用dialog呈現在另一個畫面
    請問該怎麼做呢?

    • C.T. Leung says:

      你按的「編輯」,應該是指 pager 裡面那個 edit button 吧?但那個 edit 明明就是 form edit 專用的,你的這個改變也太大了吧,嘿嘿。如果是我的話,我會直接 hide 了原來的那個 edit button,然後自己新增一個 custom button ( 當然可以用回原來 edit 的 icon )。

      那個你新增的 custom button,你想用它來幹什麼都可以了吧?哈哈哈 ( 你要的無非就是 ajax + dialog 吧,應該不會有什麼難度… )。

  7. mia says:

    不好意思請問一下,如果我的欄位在編輯時不能修改,我把editable設為false但是新增的時候又想要讓這個欄位可以填寫要怎麼做呢?

    • C.T. Leung says:

      我自己的話,我會使用另一種方法,而不會把 editable 設定為 false。

      editable:true, editoptions:{readonly:'readonly'}

      在 colModel 裡,我會把 editable 設定為 true,然後在 editoption 裡設定 readonly。這樣的話,在 edit form 裡面它仍然會顯示,但會變為 readonly,不能修改。

      然後在 add form 的 afterShowForm event 加入

      $('#column_name').removeAttr('readonly');

      並且在 edit form 的 afterShowForm event 加入

      $('#column_name').attr('readonly','readonly');

      完成之後,那你就可以在 edit 時 readonly,但 add new 時就變回 editable 了。

  8. mia says:

    不好意思又來叨擾您了,想請問一個問題是,
    我在我的jqGrid有寫
    onSelectRow的function,接著我用程式去控制選取其中一列
    jQuery(grid_selector).jqGrid(‘setSelection’,1, true);
    他並沒有觸發onSelectRow的function。
    請問如果想要觸發onSelectRow的function我該怎麼做比較好呢?

    • C.T. Leung says:

      grid.jqGrid('setSelection',rowid,true);

      以上確實是正確的寫法,而且絕對會 trigger onSelectRow event。

      我想很有可能是你程式碼中的其他部分寫錯了。

  9. kate says:

    版主你好,我也想要這個功能”某欄位在編輯時不能修改,但在新增時可以新增”
    我看了上面的對話,但看不懂
    為什麼會有”在 add form 的 afterShowForm event 加入XXX ,又有在 edit form 的 afterShowForm event 加入xxx”

    因為我的認知不管是add form或是edit form,都只有一條{afterShowForm}在控制
    如果寫兩條{afterShowForm},系統怎麼知道我目前的動作,是點選工具列的edit要看第一條{afterShowForm}
    然後點選工具列的add要看第二條{afterShowForm}

    我的程式碼如下
    jQuery(“#masterGrid”).navGrid(‘#masterPager’,
    {view:true,del:false,add:true,edit:true,refresh:true,search:true},
    {beforeSubmit:beforeEditSubmit,afterSubmit:afterFormSubmit,closeAfterEdit:true,closeAfterAdd:true}
    );

    謝謝

    • C.T. Leung says:

      嗯,你應該是沒有搞清楚那個 navGrid method 的完整用法。

      jQuery("#grid_id").navGrid('#gridpager',{parameters},prmEdit, prmAdd, prmDel, prmSearch, prmView);

      根據 documentation:
      1. grid_id 就是你的 jqGrid 的 id;
      2. gridpager 就是你的 pager 的 id;
      3. {parameters} 裡,你可設定那個 pager 的 button 顯不顯示 ( view: true, del: false );
      4. prmEdit, prmAdd, prmDel, prmSearch, prmView 就是 5 個 objects,用來設定各張 form 的 property 和 events 的動作的。

      所以,有時候,我們也會如下面這般來寫 navGrid 的,以提示自己要在那裡設定那一張 form。

      jQuery("#grid_id").navGrid('#gridpager',{edit:true,add:true,del:true,search:true,view:true},
      {}, // settings for edit
      {}, // settings for add
      {}, // settings for del
      {}, // settings for search
      {} // settings for view
      );

      如果像上面,prmEdit, … 到 prmView 5 個 object 都是空白的,就表示我們全部用 default settings。但如果我們想改變某些設定,就可以如下面這樣寫。

      jQuery("#grid_id").navGrid('#gridpager',{edit:true,add:true,del:true,search:true,view:true},
      {closeOnEscape:false}, // settings for edit
      {closeOnEscape:false}, // settings for add
      {closeOnEscape:false}, // settings for del
      {closeOnEscape:false}, // settings for search
      {closeOnEscape:false} // settings for view
      );

      很明顯,每一張 form 都有自己的 properties,而且都要逐一去設定。而 event 當然也一樣,是每一張 form 獨立去設定的。

      jQuery("#grid_id").navGrid('#gridpager',{edit:true,add:true,del:true,search:true,view:true},
      {beforeSubmit: custom_function_1}, // settings for edit
      {beforeSubmit: custom_function_2}, // settings for add
      { }, // settings for del
      {}, // settings for search
      {} // settings for view
      );

      form add 和 form edit 是各自有各自的 events 的。就像上例,你可以為 form add 和 form edit 各自的 beforeSubmit event 設定不同的動作。

  10. kate says:

    原來如此,懂了
    非常感謝

  11. kate says:

    板主你好
    在add及edit時我有一個下拉選單”edittype”是select
    但是選單的內容是用ajax從另一支程式取到的一個json object,不是寫死在editoptions:{value:{}}裡
    請問,我要如何將json object放入editoptions:{value:{}}裡?
    我用$(‘#cityId’).attr(“editoptions”,cityValue); 寫法並沒有成功,因為在add及edit時,下拉選單沒有出現

    我的colModel如下
    {label:’縣市編號’,name:’cityId’,index:’cityId’,width:25,sorttype:’text’,align:’left’,
    editable:true,edittype:’select’,editrules:{required:true},
    search:true,stype:’text’,searchrules:{required:true}}

    我另外寫了一個function,已經可以用ajax方式取得縣市json object {編號:城市名稱,編號:城市名稱} 然後
    var cityValue = {};
    cityValue[‘value’]=JSON.stringify(cityJson);
    $(‘#cityId’).attr(“editoptions”,cityValue);

    以上請教,謝謝

  12. kate says:

    看到了,謝謝板主

Leave a Reply

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