返回列表 發帖

Ext JS 初探 - 美化表單的幾個簡單步驟

不久前有提到 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'){
                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
To infinity and beyond!

請問一下,下拉式選單如何可以重復的使用??

就是 按照範列作出來的下拉式選單,只能選取值一次,就不能改變了~(選完後,再選只出現該值可以選)

能不能像html裡的下拉式選單一樣,可以改變要選的值~謝謝
50 字節以內
不支持自定義 Discuz! 代碼

TOP

本帖最後由 kenber 於 2010-6-18 11:23 編輯

回覆: 請問我要新增button,但中文字按紐為何顯示不出來?
包含驗證的內容, 改貼這一段就可以囉! ^_^

<script>
        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.get('form2').un("submit", fm2.onSubmit, fm2);   
        var newbutton = new Ext.Button({   
  renderTo:'newbutton',
  text: '按鈕',   
  handler: function(){   
   
    if (fm2.isValid()) {   

      Ext.Msg.show({   
       title:'再確認一下',   
       msg: '按下 OK 就把資料送出囉,你確定嗎?',   
       buttons: Ext.Msg.OKCANCEL,   
       fn:  function(btn, text){   
            if (btn == 'ok'){   
                fm2.el.dom.submit();   
            } else if (btn == 'cancel') {   
                Ext.Msg.alert('告訴你', '你按了取消,所以不會送出!');   
            }   
        },   
       animEl: 'newbutton'  
    });   
    } else {   
      Ext.Msg.alert('訊息', '請填寫完成後再送出!');   
    }   
  }   
});  
                fm2.add(new Ext.form.TextField({
                        applyTo:'text2',
                        allowBlank: false
                })
               
                );   
                var textAreaSettings = {
                        applyTo:'ta2',
                  grow: true,   
                  allowBlank: false  
                };   
                fm2.add(new Ext.form.TextArea(textAreaSettings));  
});  

</script>

TOP

大陸錄製的中文視頻教學
http://www.dojochina.com/index.php?q=node/889

TOP

請問我要新增button,但中文字按紐為何顯示不出來?
var newbutton = new Ext.Button('newbutton', {text: '按紐'});
.
.
.
<td><div id="newbutton"></div></td>  
如果要驗證表單某些欄位的值,一定要使用Ext的語法嗎?
document.form名稱.欄位名稱.value
就沒辦法使用是嗎?

TOP

成功了!謝謝!

TOP

不好意思,這一篇已經有點過時了,那時候用的 ExtJS 版本是 v1.1,你現在用的版本可能是 v2.2 的,所以語法上會有一些差異,你可以參考 ExtJS 的 API 文件 來查看最新的語法。

我看了一下你說的那一段,語法要修改一下才能用喔:
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'}));
});
有看出差異了嗎?
To infinity and beyond!

TOP

請問我照著步驟做....
為何此行 fm2.add(new Ext.form.DateField().applyTo('dp2'));
會錯誤(物件不支援此屬性或方法)??

TOP

你需要用 ExtJS 來完成這些功能嗎? 因為 ExtJS 的特色是在於有多樣且完整的 widget 可以讓你用來開發一個類似 windows 下的軟體,有比較豐富的 UI 表現而且都是以 AJAX 來完成和 server 端的溝通。要用來做連動的下拉選單和 AutoComplete 並不是不行,而是沒有現成的套件可以很方便的套用。關於 ExtJS 的詳細資料,你可以透過 ExtJS 的官方網站看到很棒的一些 Demo: http://extjs.com/,或是看看這個用 ExtJS 完成的網站

如果單純的是需要連動的下拉選單和 AutoComplete,建議可以去一些收集 JavaScript/AJAX Library 的網站搜尋,這一篇有提到兩個,很容易可以找到一些可用的程式喔。不過因為連動選單和 AutoComplete 的實作通常都是差異很大,說不定現成的程式並不符合自己的需求,這時你可能需要一些比較基礎的 Library 像是 prototypejQuery 來自己寫一個。
To infinity and beyond!

TOP

請教如何做出連動的下拉選單???
另外此套件除了美化表單
可以做出Autocomplete的功能嗎???

TOP

返回列表 回復 發帖