jQueryのAjaxフォーム送信テンプレ

2020/06/02

jQuery

t f B! P L

こんにちは、みんな大好きひつじさん(@youmounlp)です。
 
今日はみんな大好きjQueryの記事です。

設定

  • ペラアプリ
  • ボタン押下でフォームをAPIへ送信
  • 実際にはjQueryでイベントを拾ってAPIにはAjaxでPOST
  • HTML5のバリデーション機能は使いたい
  • APIのレスポンスを使ってHTMLの一部を書き換え

典型的ペラアプリ。
 
フォーム送信の場合、関連するイベントは以下の2つ。
clickイベント:
.on( "click", handler );
.click( handler );
 
submitイベント:
.on( "submit", handler );
.submit( handler );
 
送信ボタンとしては以下の2つ
button要素: <button></button>
input要素: <input type="button"/>
 
jQueryだからたいていのブラウザでは同じ挙動をしてくれると信じたい。でもスマホとPCだと差が出るかも。
 
click/submit x button/input x PC/スマホ
 
パターンが多い…。

結果から

フォーム送信の場合、<form></form>の中で<input type="submit />"を使う。イベントハンドラはform要素のsubmitイベントをセットする。
 
郵便番号検索風のサンプル

<form id="myform">
  <fieldset>
    <legend>郵便番号検索</legend>
    <input
      type='number'
      name='myinput'
      id='myinput'
      placeholder='郵便番号を入力'
      pattern="\d{7}"
      required autoforcus
    />
    <input  
      type="submit" 
      name="mysubmit" 
      id="mysubmit" 
      value="送信"
    />
  </fieldset>
</form>

JavaScriptは以下。/cgi-bin/search.cgiに検索APIがあるとする。

<script>
$(function(){
  $("#myform").on("submit", function(event){
    event.preventDefault();

    var isvalidate = $("#myform")[0].checkValidity();
    if (isvalidate) {
      $.ajax({
        url:'/cgi-bin/search.cgi',
        type:'POST',
        data:{
          'myinput': $("#myinput").val()
        }
      })
      .done( (data) => {
        console.log(data);
      })
      .fail( (data) => {
        console.log(data);
      })
    }
  });
});
</script>

input要素とbutton要素は何が違うんですか〜?

同じです(機能的には)。

<input> 要素の button 型は完全に妥当な HTML ですが、より新しい <button>要素が、ボタンの作成にはより好まれるようになりました。

https://developer.mozilla.org/ja/docs/Web/HTML/Element/Input/button
 
閉じタグつきのbutton要素のほうが中身を色々装飾できますってことらしい。
 
以下説明ではinput要素のみ使うけどほぼ同じだと思ってもらえれば。
 
ちなみに「機能的に同等」とあるが、機能を決めるのは要素ではなくtype属性の値。
 
type="button"とするとただのクリックできるだけのボタン
type="submit"とするとフォームのsubmitイベントが発生するボタンになる。

onclickとclick、onsubmitとsubmitは何が違うんですか〜?

同じです。

This method is a shortcut for .on( "click", handler )
This method is a shortcut for .on( "submit", handler )

https://api.jquery.com/click/
https://api.jquery.com/submit/
 
ショートカットってだけらしい。私は.on()のほう使ってるけど記事中では長さの関係でショートカットのほうで表記している。

で、どう組み合わせればいいの

<input type="button />"要素に対しては.click()を使う。
<form></form>"要素に対しては.submit()を使う。
 
そもそも適用する対象が違う。
 
フォーム送信以外の汎用的なアクションの起点にしたい場合、<input type="button />"要素を使う。
 
フォーム送信の場合、<form></form>の中では<input type="submit />"を使う。
 
formの中で<input type="button />"を使い、.click()でイベントを拾って、そのあとAjaxでpost、、、という実装もできなくはない。
 
けど、ユーザーに何かしらのデータを送信させる以上、ボタンの上には
<input type='text' />なりがあるはず。これにフォーカスしている状態でEnterキーを押すと大抵のブウザではフォームを送信する1

この場合、submitイベントが発生するので.click()ではキャッチできない。そのため、画面更新を伴う通常のForm送信が発生する
 
Ajaxを使うつもりならform要素のaction属性は何も書いてないはずなので、書いていない場合は、その画面(フォーム画面)と同じURLへのGETリクエストが発生する。
 
画面が更新されてAjaxの取得結果は消えるし、ブラウザのアドレスバーにGETリクエストのクエリパラメータが露出するしで、明らかに実装ミスっぽい感じになる。
 
なお、<input type="submit />"の場合は、他のinput要素で誤ってEnterキーを押してフォーム送信してしまった場合でも、clickイベントは発生する仕様っぽい。なので.click()をセットしていてもキャッチできる、けれどform要素に.submit()が無難かな。

どっちがいいの

PC/スマホの軸でいうと、スマホの仮想キーボードはEnterキー相当のキーを押しても、submitせず次のinput要素へよしなにフォーカス遷移してくれる印象がある。
 
とはいえ、PC/スマホで実装をわける必要もないので、冒頭の結論で書いたとおり、form要素を使うのであれば、form要素にsubmitイベントをセットするのが一番よさそう。
 
というかよく考えたら本質的にキャッチしたいイベントはsubmitイベントなんだから.submit()を使う、これだけで良いか。

まとめ

状態管理が複雑なアプリならVueやReactなんだろうけど、jQueryにはAjaxも同梱されてるし、ちょっとしたミニアプリなら必要十分感がある。自分でテンプレを作っておいて使いまわすとよさそう。
 
あと、ユーザーからの入力をブラウザに表示し返す場合は、適切にエスケープ処理を行い、XSSに気をつけましょう。


  1. 入力途中に誤ってフォーム送信してしまった経験が誰しも…。 ↩︎

ラベル

QooQ