表單提交(submit)時使用preventDefault可能產生的問題


作者: | 2011/04/12 | 1 則迴響



在表單內的任一輸入框按下Enter後,預設情況下表單會自動提交,若使用preventDefault阻止後,表單將從此不能Submit,怎麼辦?

一般我們設計HTML表單後,若在Form內的文字框按下Enter,預設會觸發Submit事件,造成表單提交。但若有某些文字框我們有特別的用途,希望它按下Enter後不要Submit表單,而是去做一些特定的動作,此時我們可以先使用preventDefault,之後再讓表單可以被Submit嗎?

舉例來說,假設我們設計了一個表單,裡面有一個可輸入「代號」的文字框,以及一個會出現該代號對應的「名稱」文字框。

這時需求要的情境是,輸入代號後,按下Enter,名稱文字框就會立即出現該代號對應的名稱,經過使用者判斷確認這是他要選的代號及名稱,才按下submit鍵送出結果。

我們先做form的設計,如下:
[code lang=”html”]
<form id=”new” action=”” method=”POST”>
    <input type=”text” id=”code” name=”code”> <!– 代號輸入框 –>
    <input type=”text” id=”name” name=”name”> <!– 名稱出現框 –>
    <input type=”submit” id=”submit” value=”提交” />
</form>
[/code]
好的,接著我們用jQuery來撰寫「在代號框輸入數值後會自動出現對應名稱」的程式碼:
[code lang=”javascript”]
$(function(){
    // 偵測若在代號框輸入值後,按下Enter,就填進對應的名稱 
    $(‘#code’).keydown(function(e){
        // Enter鍵值為13
        if (e.keyCode == ’13’) {
            // 觸發填值的動作,在此省略
        }
    });
});
[/code]

此時問題就會發生了,因為在還沒執行到填值時,我們的Enter動作早已先觸發了submit鍵的click動作,對應名稱都還沒出現,表單就被提交了。
這時也許你會想到要使用preventDefault()去阻擋預設的提交動作:
[code lang=”javascript”]
$(function(){
    // 偵測若在代號框輸入值後,按下Enter,就填進對應的名稱
    $(‘#code’).keydown(function(e){
        // Enter鍵值為13
        if (e.keyCode == ’13’) {
            // 觸發填值的動作,可能用get或load等ajax取值…
        }
    });

    // 表單的submit都會進來這兒
    $(‘#submit’).click(function(e){
        e.preventDefault(); // 成功阻擋Enter的submit動作!
    });
});
[/code]
是的,成功阻擋了submit,但是若您手動去按提交鍵會發現submit動作也被擋了,再也提交不出表單了XD。於是有人會問,如何在使用過e.preventDefault後,再一次讓submit復活呢(reenable submit)!?? 唉,我也沒試出來XD,不過在此可以使用一個workaround的方式解決。

重新解讀我們想完成的事情就是–希望submit事件不要在代號框取得focus時會return true,讓它好好的做它該做的事:去把名稱填好。了解這樣的方式後,解決方式幾乎就呼之欲出了:
[code lang=”javascript”]
$(function(){
    // 用來判斷是否submit的flag
    var fSubmit = false;

    // 偵測若在代號框輸入值後,按下Enter,就填進對應的名稱
    $(‘#code’).keydown(function(e){
        // Enter鍵值為13
        if (e.keyCode == ’13’) {
            // 觸發填值的動作,可能用get或load等ajax取值
        }
    }).focus(function(){ // 代號框取得focus,這時擋下所有的submit事件
        fSubmit = false;
    }).blur(function(){
        fSubmit = true; //代號框失去focus,這時允許submit
    })

    // 表單的submit都會進來這兒
    $(‘form’).submit(function(e){
        return fSubmit; // 傳回true就會submit,傳回false就表示不作submit
    });
});
[/code]
如此就可以滿足一開始所提的需求。
至於如何在使用過preventDefault後再次submit呢?期待各位先進可以分享,感謝!


標籤:,

分類:,

本文作者是Audi Lu

1 則留言

  • sheephead says:

    你好喔
    ㄏ 你們的文章寫得很讚
    不過就這個範例而言應該不用那麼麻煩

    只要在按下ENTER裡面的判斷最後加上e.preventDefault();就可以了
    不用特意去處理submit那一段程式碼。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

*

*

*

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料