不久前有提到 Ext JS 推出新版後我才開始注意到了 Ext JS,官方網頁上的表單範例做的蠻簡潔美觀的,不會有過度裝飾的感覺 (完全是個人主觀偏好喔),這種內斂的美感正是我所想要的風格,因此馬上有了想利用 Ext JS 來改造目前現有的表單這樣的一個想法,以下是一些些的心得分享,希望能對想使用 Ext JS 的人有些幫助。
這是一個很單純的表單,有文字輸入框、下拉選單、日期輸入(目前看到的還是單純的文字輸入)、多行文字輸入及一個送出的按鈕:
<form id="form2" method="post"><h3>表單範例</h3><table> <tr> <td class="title">文字輸入:</td> <td style="font-family: verdana;"><input type="text" id="text2" name="text2" /></td> </tr> <tr> <td class="title">下拉選單:</td> <td style="font-family: verdana;"><select id="st2" name="st2"> <option></option> <option>Aeiou</option> <option>Andy</option> <option>Amy</option> <option>Aloha</option> <option>Apple</option> <option>Application</option> <option>Aprik</option> <option>Backup</option> <option>Book</option> </select> </td> </tr> <tr> <td class="title">日期選擇:</td> <td style="font-family: verdana;"><input type="text" id="dp2" name="dp2" /></td> </tr> <tr> <td class="title">多行輸入:</td> <td><textarea id="ta2" name="ta2" cols="50" rows="6"></textarea></td> </tr> <tr> <td class="title"> </td> <td> <input type="submit" id="bt2" name="bt2" value="按鈕" /> </td> </tr></table></form>
現在我們要做的就是透過 Ext JS 所提供的功能來改造這個表單,除了要讓表單看起來漂亮一點之外,還可以加入一些和 user 互動的對話框以及基本的輸入條件檢查。如果你有看過 Ext JS 所提供的範例,你會發現 Ext JS 可以動態的產生表單,不過我想還是有很多人的需求會是需要改變現有的表單,一方面是現有的系統就可以直接拿來改造了,另一方面是表單畫面可能都是設計人員或美工作好的,用動態產生表單的話要怎麼和他們溝通啊,是吧?等我有機會做個 one page application 的時候再來考慮動態產生表單好了。
首先要準備 Ext JS 的最新版本,請直接上官方網站去下載並解開壓縮檔。先解釋一下我所了解的 Ext JS 運作方式,在 Ext JS 一開始的版本並不是可以獨立運作的,而是架構在例如 prototype 或 YUI 的一些基本 function 之上,所以你可以看到在解開的檔案中有個 adapter 的目錄,底下是各個不同 library 的橋接程式。但是在目前最新的 v1.1 版內,Ext JS 自己寫了一組相似的 function,因此只要使用 v1.1 以上的版本,就可以獨立運作不用搭配其他 library 了。這次的範例當然也是選擇搭配內建的 library 以求方便,以下是你在網頁內需要引用的 js 和 css:
<link rel="stylesheet" type="text/css" href="resources/css/ext-all.css" /><script type="text/javascript" src="adapter/ext/ext-base.js"></script><script type="text/javascript" src="ext-all.js"></script>
這邊要再解釋一下,Ext JS 完整 library 的檔案也不算小,所以和其他 library 一樣,你可以選擇性的 include 要使用的 function 即可,包含 js 和 css,我們為了方便起見,直接引用 ext-all.css 和 ext-all.js。官方網站有提供 Build your own Ext 的功能,可以讓你挑出你所需要的功能再幫你壓縮並且讓你下載。
第一步:先加個外框吧
幫你的表單加個美美的外框很容易,只要你剛引用的 ext-all.css 路徑正確,再加入以下的 html 即可:
<div class="x-box-tl"><div class="x-box-tr"><div class="x-box-tc"></div></div></div> <div class="x-box-ml"><div class="x-box-mr"><div class="x-box-mc"> 這邊放你原本的表單 </div></div></div><div class="x-box-bl"><div class="x-box-br"><div class="x-box-bc"></div></div></div>
順利的話,你的表單已經看起來不太一樣了:
第二步:Ext.form.BasicForm 粉墨登場
該 JavaScript 登場了,Ext.form.BasicForm 可以用來改造現有的表單,除了簡單的美化、可以有輸入驗證外,下拉選單可以直接變成有自動完成的功能、也提供以月曆選擇日期的功能等等。你需要加入以下的 JavaScript:
Ext.onReady(function(){ var fm2 = new Ext.form.BasicForm('form2'); fm2.add(new Ext.form.TextField().applyTo('text2')); fm2.add(new Ext.form.ComboBox({transform:'st2'})); fm2.add(new Ext.form.DateField().applyTo('dp2')); fm2.add(new Ext.form.TextArea().applyTo('ta2'));})
Ext.onReady() 可以讓裡面的程式等到網頁載入完成後再執行,因為我們是利用現成的表單來做加強,所以必須確保網頁載入完成再做,這樣才不會有問題。從 new Ext.form.BasicForm() 開始,依序就是建立 BasicForm,加入 TextField、ComboBox、DateField、TextArea,你可以看到 new Ext.form.TextField().applyTo('text2') 這樣的語法就是直接將 id=text2 的這個欄位以 Ext JS 的 TextField 來套用,不同的是下拉選單做法不太一樣,必須使用 transform 這個參數傳入我們要改造的下拉選單的 id。先來看一下成果吧:
比較不一樣的地方就是下拉選單和輸入日期的欄位,有了 Ext JS 的加持後,馬上加入了特異功能。眼尖的人可能注意到了,我們還沒去動到表單原本的按鈕,沒錯,因為 Ext JS 沒有提供類似上面用到的技巧可以直接將表單的按鈕給取代掉,所以我們必須用不同的方式來產生按鈕,而且必須將原本表單內的按鈕給移除掉。
第三步:加入按鈕
先修改一下原本的 html ,把按鈕先隱藏或移除掉,再加入一個 newbutton 的 div 如下:
<!--input type="submit" id="bt2" name="bt2" value="按鈕" /--><div id="newbutton"></div>
Ext.onReady() 內再加入這一段:
var newbutton = new Ext.Button('newbutton', {text: '按鈕'});
這樣按鈕就順利加入了:
目前這個的按鈕是沒有任何作用的,我們得再加入一些料。在這之前先提示一下,在 Ext JS 的設計中,表單的 submit 方式都是以 Ajax 的方式在運作,而不是傳統的 post 到另一頁的方式。當我們用了 Ext.form.BasicForm 的時候,這個 form 的 submit 事件就已經被攔截了,即使原本表單內的 submit 按鈕也不會有作用,所以我們得先將這個攔截掉 submit 事件的 listener 給取消掉,然後在新增的 button 內加入事件的處理。剛那一段新增 button 的程式碼就先 remark 掉,換上一段新的:
//var newbutton = new Ext.Button('newbutton', {text: '按鈕'});Ext.get('form2').un("submit", fm2.onSubmit, fm2);var newbutton = new Ext.Button('newbutton', { text: '按鈕', handler: function(){ if (fm2.isValid()) { Ext.Msg.show({ title:'再確認一下', msg: '按下 OK 就把資料送出囉,你確定嗎?', buttons: Ext.Msg.OKCANCEL, fn: function(btn, text){ if (btn == 'ok'){ &nbs; fm2.el.dom.submit(); } else if (btn == 'cancel') { Ext.Msg.alert('告訴你', '你按了取消,所以不會送出!'); } }, animEl: 'newbutton' }); } else { Ext.Msg.alert('訊息', '請填寫完成後再送出!'); } }});
上面這一段先用了 Ext.get('form2').un("submit", fm2.onSubmit, fm2) 把這個 form 的 submit listener 給取消掉,接著新增 button 並指定處理的事件。fm2.isValid() 是判斷這個 form 裡面的欄位驗證是否通過,嘿嘿,不過我們還沒把驗證的功能加入到欄位中,等會兒會再看到。另外還用到了 Ext.Msg.show() 和 Ext.Msg.alert() 來顯示訊息,詳細的參數就不多解釋了,看一下訊息的畫面好了:
第四步:基本驗證功能
對於表單比較實用的功能應該就是表單的驗證了,最基本的就是欄位是否有輸入值,我們可以透過參數來設定。在產生欄位的同時可以傳入很多樣的參數,例如:
fm2.add(new Ext.form.TextField({allowBlank: false}).applyTo(Ext.get('text2')));var textAreaSettings = { grow: true, allowBlank: false};fm2.add(new Ext.form.TextArea(textAreaSettings).applyTo(Ext.get('ta2')));
產生 TextField 的同時傳入了 allowBlank: false,這就是代表這個欄位不能有空白。另外在產生 TextArea 的同時傳入了多個參數,包括高度自動增加及不能有空白,自動增高的功能聽起來相當不錯是吧,應該是非常適合 TextArea 這種欄位的,不過 Ext JS 的這個功能似乎有點小小的 bug,因為增高的幅度似乎會越來越大,目前還不算很實用。詳細的參數大家可以參考 API 文件(在下載的壓縮檔的 docs 目錄下就可以看到了),有相當多的設定是可以參數化調整的。
加入了以上兩個欄位的基本驗證後,當我們按下按鈕要送出時,就會先出現警告訊息,而且相關的欄位也會有變化如下:
第五步:再裝飾一下
完成了以上的步驟之後,其實已經達到了我們的目標了,但是下面這個功能不介紹一下的話實在對不起大家,因為只要加入短短的一行程式碼就立即有效,而且還蠻實用的喔。只要在 Ext.onReady() 裡面加入一行:
Ext.QuickTips.init();
直接來看看成果吧:
當滑鼠游標停留在那些未完成的欄位時,都會出現一個小小的浮動區塊提示相關訊息,你是不是在想說那些怎麼都是英文的啊?嘿嘿,當然都是可以透過參數去修改的,這些就留給大家去練習練習囉。
以上完整範例可以在此直接測試或查詢原始碼:
http://jsgears.com/_demo/index.php