jQuery

【実践】jQueryフォーム操作ガイド - val/serialize/バリデーション

カービー
【実践】jQueryフォーム操作ガイド - val/serialize/バリデーション
#jQuery#フォーム#JavaScript#バリデーション#Web開発

jQueryでのフォーム操作を完全解説。val()、serialize()、バリデーション、リアルタイム入力チェック、送信処理まで実践的なサンプルコード付き。

目次

  1. フォーム要素の値を取得・設定
  2. フォームのシリアライズ
  3. フォームイベント
  4. バリデーション
  5. 実践的なサンプル
  6. まとめ

フォーム要素の値を取得・設定

val() - 基本的な値の操作

// 値の取得
let value = $('#username').val();

// 値の設定
$('#username').val('新しい値');

// 値をクリア
$('#username').val('');

テキスト入力

<input type="text" id="username" value="初期値">
<textarea id="message">テキストエリアの内容</textarea>
// input[type="text"]
let username = $('#username').val();
$('#username').val('山田太郎');

// textarea
let message = $('#message').val();
$('#message').val('新しいメッセージ');

セレクトボックス

<select id="prefecture">
    <option value="">選択してください</option>
    <option value="tokyo">東京都</option>
    <option value="osaka">大阪府</option>
    <option value="kyoto">京都府</option>
</select>

<select id="hobbies" multiple>
    <option value="sports">スポーツ</option>
    <option value="music">音楽</option>
    <option value="reading">読書</option>
</select>
// 単一選択
let prefecture = $('#prefecture').val();           // "tokyo"
$('#prefecture').val('osaka');                     // 大阪府を選択

// 選択されたテキストを取得
let prefText = $('#prefecture option:selected').text();  // "東京都"

// 複数選択
let hobbies = $('#hobbies').val();                 // ["sports", "music"]
$('#hobbies').val(['sports', 'reading']);          // 複数選択

ラジオボタン

<input type="radio" name="gender" value="male"> 男性
<input type="radio" name="gender" value="female"> 女性
<input type="radio" name="gender" value="other"> その他
// 選択された値を取得
let gender = $('input[name="gender"]:checked').val();

// 特定の値を選択
$('input[name="gender"][value="male"]').prop('checked', true);

チェックボックス

<input type="checkbox" name="agree" id="agree"> 同意する
<input type="checkbox" name="options" value="a"> オプションA
<input type="checkbox" name="options" value="b"> オプションB
<input type="checkbox" name="options" value="c"> オプションC
// チェック状態の取得
let isAgreed = $('#agree').prop('checked');  // true/false
let isAgreed2 = $('#agree').is(':checked');  // true/false

// チェック状態の設定
$('#agree').prop('checked', true);   // チェックを入れる
$('#agree').prop('checked', false);  // チェックを外す

// 複数チェックボックスの値を取得
let options = [];
$('input[name="options"]:checked').each(function() {
    options.push($(this).val());
});
// または
let options2 = $('input[name="options"]:checked').map(function() {
    return $(this).val();
}).get();  // ["a", "c"]

フォームのシリアライズ

serialize()

フォームデータをURLエンコードされた文字列に変換します。

<form id="myForm">
    <input type="text" name="username" value="山田">
    <input type="email" name="email" value="yamada@example.com">
    <select name="prefecture">
        <option value="tokyo" selected>東京都</option>
    </select>
</form>
let formData = $('#myForm').serialize();
// 結果: "username=%E5%B1%B1%E7%94%B0&email=yamada%40example.com&prefecture=tokyo"

serializeArray()

フォームデータを配列形式で取得します。

let formArray = $('#myForm').serializeArray();
// 結果:
// [
//     { name: "username", value: "山田" },
//     { name: "email", value: "yamada@example.com" },
//     { name: "prefecture", value: "tokyo" }
// ]

// オブジェクトに変換
let formObject = {};
$.each(formArray, function() {
    formObject[this.name] = this.value;
});
// { username: "山田", email: "yamada@example.com", prefecture: "tokyo" }

フォームデータをオブジェクトに変換する関数

$.fn.serializeObject = function() {
    let obj = {};
    let array = this.serializeArray();

    $.each(array, function() {
        if (obj[this.name]) {
            if (!Array.isArray(obj[this.name])) {
                obj[this.name] = [obj[this.name]];
            }
            obj[this.name].push(this.value);
        } else {
            obj[this.name] = this.value;
        }
    });

    return obj;
};

// 使用
let data = $('#myForm').serializeObject();

フォームイベント

submit - フォーム送信

$('#myForm').on('submit', function(e) {
    e.preventDefault();  // デフォルトの送信を防ぐ

    // バリデーション
    if (!validateForm()) {
        return;
    }

    // Ajax送信
    $.ajax({
        url: '/api/submit',
        type: 'POST',
        data: $(this).serialize(),
        success: function(response) {
            alert('送信完了');
        }
    });
});

change - 値の変更

// セレクトボックスの変更
$('#prefecture').on('change', function() {
    let value = $(this).val();
    console.log('選択された値:', value);
});

// チェックボックスの変更
$('#agree').on('change', function() {
    let isChecked = $(this).prop('checked');
    $('#submitBtn').prop('disabled', !isChecked);
});

// ファイル選択
$('#fileInput').on('change', function() {
    let file = this.files[0];
    if (file) {
        console.log('ファイル名:', file.name);
        console.log('サイズ:', file.size);
    }
});

input - リアルタイム入力

// 入力中にリアルタイムで処理
$('#searchInput').on('input', function() {
    let value = $(this).val();
    console.log('入力中:', value);
});

// 文字数カウント
$('#message').on('input', function() {
    let length = $(this).val().length;
    $('#charCount').text(length + '/200');

    if (length > 200) {
        $(this).addClass('error');
    } else {
        $(this).removeClass('error');
    }
});

focus / blur - フォーカス

// フォーカス時
$('input').on('focus', function() {
    $(this).addClass('focused');
    $(this).parent().find('.hint').show();
});

// フォーカスが外れた時
$('input').on('blur', function() {
    $(this).removeClass('focused');
    $(this).parent().find('.hint').hide();

    // バリデーション実行
    validateField($(this));
});

バリデーション

基本的なバリデーション

function validateForm() {
    let isValid = true;
    let errors = [];

    // 必須チェック
    if ($('#username').val().trim() === '') {
        errors.push('ユーザー名を入力してください');
        $('#username').addClass('error');
        isValid = false;
    }

    // メール形式チェック
    let email = $('#email').val();
    let emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    if (!emailRegex.test(email)) {
        errors.push('正しいメールアドレスを入力してください');
        $('#email').addClass('error');
        isValid = false;
    }

    // 文字数チェック
    let password = $('#password').val();
    if (password.length < 8) {
        errors.push('パスワードは8文字以上で入力してください');
        $('#password').addClass('error');
        isValid = false;
    }

    // エラー表示
    if (!isValid) {
        $('#errorList').html(errors.map(e => `<li>${e}</li>`).join(''));
    }

    return isValid;
}

$('#myForm').on('submit', function(e) {
    e.preventDefault();

    // エラークラスをリセット
    $('input').removeClass('error');
    $('#errorList').empty();

    if (validateForm()) {
        // 送信処理
        $(this).submit();
    }
});

リアルタイムバリデーション

// 入力フィールドごとのバリデーション
function validateField($field) {
    let name = $field.attr('name');
    let value = $field.val().trim();
    let $error = $field.siblings('.error-message');

    $field.removeClass('error success');
    $error.text('');

    switch (name) {
        case 'username':
            if (value === '') {
                $field.addClass('error');
                $error.text('ユーザー名は必須です');
                return false;
            }
            if (value.length < 3) {
                $field.addClass('error');
                $error.text('3文字以上で入力してください');
                return false;
            }
            break;

        case 'email':
            if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) {
                $field.addClass('error');
                $error.text('正しいメールアドレスを入力してください');
                return false;
            }
            break;

        case 'password':
            if (value.length < 8) {
                $field.addClass('error');
                $error.text('8文字以上で入力してください');
                return false;
            }
            if (!/[A-Z]/.test(value)) {
                $field.addClass('error');
                $error.text('大文字を含めてください');
                return false;
            }
            break;
    }

    $field.addClass('success');
    return true;
}

// blur時にバリデーション
$('input').on('blur', function() {
    validateField($(this));
});

// パスワード強度チェック
$('#password').on('input', function() {
    let password = $(this).val();
    let strength = 0;

    if (password.length >= 8) strength++;
    if (/[a-z]/.test(password)) strength++;
    if (/[A-Z]/.test(password)) strength++;
    if (/[0-9]/.test(password)) strength++;
    if (/[^a-zA-Z0-9]/.test(password)) strength++;

    let labels = ['', '弱い', '普通', '強い', '非常に強い', '最強'];
    let colors = ['', '#ff4444', '#ffaa00', '#88cc00', '#00aa00', '#006600'];

    $('#passwordStrength')
        .text(labels[strength])
        .css('color', colors[strength]);
});

確認用入力のチェック

$('#confirmPassword').on('input', function() {
    let password = $('#password').val();
    let confirm = $(this).val();

    if (password !== confirm) {
        $(this).addClass('error');
        $(this).siblings('.error-message').text('パスワードが一致しません');
    } else {
        $(this).removeClass('error').addClass('success');
        $(this).siblings('.error-message').text('');
    }
});

実践的なサンプル

会員登録フォーム

<form id="registrationForm">
    <div class="form-group">
        <label for="username">ユーザー名 <span class="required">*</span></label>
        <input type="text" id="username" name="username" required>
        <span class="error-message"></span>
    </div>

    <div class="form-group">
        <label for="email">メールアドレス <span class="required">*</span></label>
        <input type="email" id="email" name="email" required>
        <span class="error-message"></span>
    </div>

    <div class="form-group">
        <label for="password">パスワード <span class="required">*</span></label>
        <input type="password" id="password" name="password" required>
        <span class="password-strength"></span>
        <span class="error-message"></span>
    </div>

    <div class="form-group">
        <label for="confirmPassword">パスワード(確認)</label>
        <input type="password" id="confirmPassword" name="confirmPassword">
        <span class="error-message"></span>
    </div>

    <div class="form-group">
        <label>
            <input type="checkbox" id="agree" name="agree" required>
            利用規約に同意する
        </label>
    </div>

    <button type="submit" id="submitBtn" disabled>登録する</button>
</form>
$(function() {
    // フォームの状態を監視
    function updateSubmitButton() {
        let isValid = true;

        // 必須フィールドのチェック
        $('#registrationForm input[required]').each(function() {
            if ($(this).attr('type') === 'checkbox') {
                if (!$(this).prop('checked')) isValid = false;
            } else {
                if ($(this).val().trim() === '') isValid = false;
            }
        });

        // エラーがないかチェック
        if ($('#registrationForm .error').length > 0) {
            isValid = false;
        }

        $('#submitBtn').prop('disabled', !isValid);
    }

    // 入力変更時にボタン状態を更新
    $('#registrationForm input').on('input change', updateSubmitButton);

    // フォーム送信
    $('#registrationForm').on('submit', function(e) {
        e.preventDefault();

        let $form = $(this);
        let $btn = $('#submitBtn');

        // ボタンを無効化
        $btn.prop('disabled', true).text('送信中...');

        $.ajax({
            url: '/api/register',
            type: 'POST',
            data: $form.serialize()
        })
        .done(function(response) {
            alert('登録が完了しました');
            $form[0].reset();
        })
        .fail(function(xhr) {
            let error = xhr.responseJSON?.message || '登録に失敗しました';
            alert(error);
        })
        .always(function() {
            $btn.prop('disabled', false).text('登録する');
        });
    });
});

動的フォーム(項目の追加・削除)

<form id="dynamicForm">
    <div id="itemsContainer">
        <div class="item-row">
            <input type="text" name="items[]" placeholder="項目名">
            <button type="button" class="remove-btn">削除</button>
        </div>
    </div>
    <button type="button" id="addItem">項目を追加</button>
    <button type="submit">送信</button>
</form>
// 項目を追加
$('#addItem').on('click', function() {
    let newRow = `
        <div class="item-row">
            <input type="text" name="items[]" placeholder="項目名">
            <button type="button" class="remove-btn">削除</button>
        </div>
    `;
    $('#itemsContainer').append(newRow);
});

// 項目を削除(イベント委譲)
$('#itemsContainer').on('click', '.remove-btn', function() {
    let rowCount = $('.item-row').length;
    if (rowCount > 1) {
        $(this).closest('.item-row').remove();
    } else {
        alert('最低1つの項目が必要です');
    }
});

まとめ

よく使うメソッド

メソッド 用途
.val() 値の取得・設定
.prop('checked') チェック状態の取得・設定
.serialize() フォームデータを文字列化
.serializeArray() フォームデータを配列化
.prop('disabled') 有効/無効の切り替え

フォーム操作のポイント

  1. val() は入力要素の値操作に使用
  2. prop() はチェックボックス、disabled、selectedなどに使用
  3. serialize() はAjax送信時に便利
  4. バリデーション はリアルタイムとsubmit時の両方で行う
  5. イベント委譲 は動的に追加される要素に必須

jQueryのフォーム操作をマスターして、ユーザーフレンドリーなフォームを作りましょう。