jQueryでフォーム内のデータを配列で取り出す



2016年1月に jQueryも約9ヶ月ぶりにアップデートされ、
バージョンも 2系は2.2.*  1系は1.13.* になりました。

Web開発ではjQuery依存からの脱却等の記事も目にするようになりましたが
多くのプロジェクトで使われており、まだまだ第一線です。
( Bootstrap等のCSSフレームワークもjQueryに依存しています )

ajax ( 非同期通信 ) でフォームのデータを送信 ( POST ) する際は
jQueryを使ってフォーム内のデータを取り出すことが多いと思います。

idベースで値を取得する時は下記の様な感じが多いのではないでしょうか。

$('#inputData').val(); // id="inputData"の値を取得

値を取る為には、上記のコードでも問題ないのですが
フォーム内のデータが多いと どうしてもコードが長くなってしまいます。
( * フォーム内にデータを埋め込む際は問題ありません )

// ファーム内のデータが長いとコードも長くなります
var data = {
 first_name : $('#firstName').val(),
 last_name : $('#lastName').val(),
 description: $('#description').val(),
 ...
 ...
 }

jQueryにはserializeArray()という便利な関数が用意されており、
その関数を使うとform内のデータが配列で取得出来ます。

しかしながら、serializeArray()関数を そのまま使うと
1つのフォームデータ毎に"name", "value"のオブジェクトで返ってくるので、
使い勝手がよくありません。

// id="submitForm"をクリックした時の処理
$('#submitForm').on('click', function() {
  // id='loginForm'内のnameの値を取得
  var data = $('#loginForm').serializeArray();

  /*-- output --
  object{ name : "username", value: "YourName"}
  object{ name " "password", value: "YourPassword" }
  */
  console.log(data);
});

そのままで送信(POST)すると、思っていた通りにデータが送信出来ないので
POST用にデータを加工する必要があります。

/* -- 欲しいデータ形式 --
Object {username: "YourUsername", password: "YourPassword"}
*/


それでは下記のformサンプルを使ってさまざまなデータ加工をしてみます。
jQuery単体だけではなく、underscore.jslodash.jsと組み合わたサンプルも載せておきます。

<!-- login Form *tokenは割愛しています  -->
<form class="form-group" id="loginForm" >
  
  <label for="username">username:</label>
    <input type="text" class="form-control" id="username" name="username" value="" />
    
  <label for="pass">password:</label>
    <input type="password" class="form-control" id="password" name="password" value="" />
		
    <br>
  <!-- submit button -->
  <span id="submitForm" class="btn btn-primary">login</span>
  
</form>


jQueryを拡張する場合

jQueryを直接拡張して、serializeObjectという関数を作成する方法です。
serializeArray関数のようにidをいれれば、フォーム内のnameの値を配列として返します。
( 参考にしたサイト: StackOverlow )

// extends jquery
$.fn.serializeObject = function()
{
    var object = {};
    var array = this.serializeArray();
    
    $.each(array, function() {
        if (object[this.name] !== undefined) {
            if (!object[this.name].push) {
                object[this.name] = [object[this.name]];
            }
            object[this.name].push(this.value || '');
        } else {
            object[this.name] = this.value || '';
        }
    });
    
    return object;
};

// 使い方 *how to use
var out = $('#loginForm').serializeObject();

console.log(out);


underscore.jsを使う場合

underscore.jsを使ったサンプルです。上記のjQueryを拡張する方法よりコンパクトに書けます!
backbone.jsを使っているプロジェクトにはそのまま使えそうです。
underscore.js 1.8.3とlodash.js 3.10.1では動きますが lodash.js 4.0では動きません
( 参考にしたサイト: Qiita - serializeArrayをname:valueのオブジェクトに変換 )

/* -- Working well -- */
// underscore.js ver 1.8.3 lodash.js v3.10.1 
/* -- Doesn't work -- */
// lodash.js ver 4
var data = _.chain($('#loginForm').serializeArray())
            .map( function(i) { return [i.name, i.value]; } )
            .object().value();
// output
console.log(data);


lodash.jsを使う場合

最後にlodash.jsを使った例です。
こちらはunderscore.jsで記述した場合より、シンプルでわかり易く書くことが出来ます。
lodash.js 3.10.1, 4.0で動作検証しました。
( *undersore.jsでは動きません )

/* -- working well --
* lodash.js ver 3.10.1, 4.0
*/
var data =
    _.chain($('#loginForm').serializeArray())
      .mapKeys(function(i){ return i.name; })
      .mapValues(function(i){ return i.value; })
      .value();

// output
console.log(data);


Summary

以上3つのサンプルでした!
上記で紹介したサンプルを使えばformのデータ取得が簡単になります。

また、underscore.jsやlodash.jsをお使いの方は
_.mixin関数を使って拡張すれば使い回すことが出来ます。

// this is for lodash.js
_.mixin({
  // require jQuery
  serializeObject : function(formID) {
          return _.chain($(formID).serializeArray())
                  .mapKeys(function(i){ return i.name; })
                  .mapValues(function(i){ return i.value; })
                  .value();
          }
});

// how to use
console.log(_.serializeObject('#someForm'));


様々な場面で使えると思うのでゼヒ×2参考にしてください!

 

この記事のカテゴリ
プログラミング

この記事のタグ