本文へスキップ

フォームの送信イベントとバリデーション

ce.formpre_ と ce.formpost_ の使い分け、バリデーション通過後の非同期処理、JavaScript での翻訳の使い方。

更新日: Markdown で表示

フォームの送信の前後にカスタム処理を追加する方法です。追加のバリデーション、確認ダイアログ、送信データの加工、外部 API との非同期通信などに使います。CS-Cart 4.19.1 で確認した内容です。

フォームのイベント

イベント名 タイミング 用途
ce.formpre_[FORM_NAME] 標準のバリデーションの前 追加のチェック、確認、データの加工
ce.formpost_[FORM_NAME] 標準のバリデーションを通過した後 バリデーション通過後の処理
ce.formajaxpost_[FORM_NAME] AJAX 送信の後 AJAX 送信後の処理

ハンドラーが false を返すと、送信はキャンセルされます。true を返すか、何も返さなければ、送信を続けます。同じイベントに複数のハンドラーを登録でき、すべて実行されます。1つでも false を返すと、送信はキャンセルされます。

[FORM_NAME] には、フォームの name 属性を入れます。name 属性のないフォームは、フックできません。

<form action="" method="post" name="product_update_form">
                                    ^^^^^^^^^^^^^^^^^^^
                                    これがフォーム名。イベント名は ce.formpre_product_update_form になる

基本の書き方

(function (_, $) {
    'use strict';

    // フォーム送信前のフック
    $.ceEvent('on', 'ce.formpre_my_form', function (form, clicked_elm) {
        // form: 送信されるフォーム(jQuery オブジェクト)
        // clicked_elm: クリックされた要素(jQuery オブジェクト)

        // false を返すと送信をキャンセルする
    });

})(Tygh, Tygh.$);

ハンドラーの引数から、次のような情報を取り出せます。

$.ceEvent('on', 'ce.formpre_product_update_form', function (form, clicked_elm) {
    var formName = form.attr('name');               // フォーム名
    var formAction = form.attr('action');           // 送信先の URL
    var formData = form.serialize();                // フォームのデータ
    var buttonName = clicked_elm.attr('name');      // ボタンの name
    var buttonValue = clicked_elm.val();            // ボタンの値
    var dispatch = clicked_elm.data('ca-dispatch'); // dispatch の値
});

使用例

送信前に確認ダイアログを出す

$.ceEvent('on', 'ce.formpre_order_form', function (form, clicked_elm) {
    // 特定のボタンのときだけ確認する
    if (clicked_elm.attr('name') === 'dispatch[orders.delete]') {
        if (!confirm('本当に削除しますか?')) {
            return false; // キャンセル
        }
    }
});

追加のバリデーションをする

$.ceEvent('on', 'ce.formpre_product_update_form', function (form, clicked_elm) {
    var codeA = form.find('#elm_code_a').val();
    var codeB = form.find('#elm_code_b').val();

    if (codeA && codeB && !validateRelation(codeA, codeB)) {
        $.ceNotification('show', {
            type: 'E',
            title: 'エラー',
            message: '2つのコードの関係が不正です'
        });
        return false; // 送信をキャンセル
    }
});

送信前にデータを加工する

$.ceEvent('on', 'ce.formpre_my_form', function (form, clicked_elm) {
    // カンマを取り除く
    var $priceField = form.find('#elm_price');
    $priceField.val($priceField.val().replace(/,/g, ''));

    // hidden フィールドを動的に追加する
    form.append('<input type="hidden" name="processed" value="1" />');
});

複数のフォームに同じ処理を適用する

['form_a', 'form_b', 'form_c'].forEach(function (formName) {
    $.ceEvent('on', 'ce.formpre_' + formName, function (form, clicked_elm) {
        return commonValidation(form);
    });
});

ce.formpre_ と ce.formpost_ の使い分け

フォームを送信する前に、外部の API と非同期で通信し、取得したトークンをフォームに入れて再送信する場合を考えます。たとえば、決済サービスのカードトークンを取得する場合です。

ce.formpre_ を使うと、次の問題が起きました。

  • 標準のバリデーションでエラーがあっても、外部の API が呼ばれる。
  • $.ceFormValidator('check', $form) が undefined を返し、cm-check-expiry のような独自のバリデーターのエラーを検知できない。

ce.formpre_ はバリデーションの前に発火するため、この時点では検証が終わっていません。バリデーションの結果が必要な処理は、ce.formpost_ を使います。

悪い例:ce.formpre_ を使う

// バリデーションの前に発火するため、エラーがあっても API が呼ばれる
$.ceEvent('on', 'ce.formpre_' + formName, function (form, elm) {
    // $.ceFormValidator('check', $form) は undefined を返す
});

良い例:ce.formpost_ を使う

// バリデーションを通過した後に発火する
$.ceEvent('on', 'ce.formpost_' + formName, function (form) {
    // トークンがあれば、そのまま送信する
    if ($('#token').val()) {
        return true;
    }

    // バリデーションを再確認する(form オブジェクトを直接使う)
    var isFormValid = form.ceFormValidator('check');
    if (isFormValid) {
        // 非同期で API を呼び出す(externalApi は、外部のサービスの SDK を想定した例)
        var data = form.serialize();
        externalApi.getToken(data, function (token) {
            $('#token').val(token);
            form[0].submit(); // フォームを再送信する
        });
    }

    return false; // 最初の送信はキャンセルする
});

実装のポイントは、次の3つです。

  1. form パラメーターを直接使います。$(form) にはしません。
  2. form.ceFormValidator('check') で、バリデーションを再確認します。
  3. トークンを取得したあとは、form[0].submit() でネイティブの送信をします。

任意のタイミングでバリデーションを実行して送信する

通常は、フォームに cm-ajax などの適切なクラスを付けるだけで、バリデーションが自動で実行されます。独自のボタンから、バリデーションを実行して送信したい場合は、$.ceFormValidator('check', $form) を使います。

$(document).on('click', '#my_submit_button', function (e) {
    e.preventDefault();

    var $form = $('#my_form');

    // true: すべてのチェックが OK、false: エラーあり
    if ($.ceFormValidator('check', $form)) {
        $form.submit();
    }
    // エラーがあれば、自動でエラーが表示される
});

AJAX で送信する場合は、$.ceAjax('request', ...) を使います。

if ($.ceFormValidator('check', $form)) {
    $.ceAjax('request', $form.attr('action'), {
        method: 'post',
        data: $form.serialize(),
        callback: function (data) {
            if (data.success) {
                $.ceNotification('show', {
                    type: 'N',
                    message: '保存しました'
                });
            }
        }
    });
}

ceFormValidator のメソッド

メソッド 説明
$.ceFormValidator('check', $form) バリデーションを実行し、結果を真偽値で返します。
$.ceFormValidator('showErrors', $form, errors) エラーを手動で表示します。
$.ceFormValidator('hideErrors', $form) エラーの表示を消します。
$.ceFormValidator('registerValidator', {...}) 独自のバリデーターを登録します。

JavaScript で言語変数(翻訳)を使う

1. テンプレートで翻訳キーを登録する

hooks/index/scripts.post.tpl

<script>
    (function(_, $) {
        _.tr({
            "my_addon.message_key":
                "{__("my_addon.message_key")|escape:"javascript"}",
            "my_addon.validation_error":
                "{__("my_addon.validation_error")|escape:"javascript"}"
        });
    }(Tygh, Tygh.$));
</script>

{script src="js/addons/my_addon/func.js"}
  • {__("キー")} で、Smarty から翻訳を取得します。
  • |escape:"javascript" で、JavaScript 用にエスケープします。必須です。
  • _.tr({...}) で、Tygh オブジェクトに登録します。

2. JavaScript で翻訳を取得する

(function (_, $) {
    'use strict';

    var message = _.tr('my_addon.message_key');

    $.ceNotification('show', {
        type: 'W',
        message: _.tr('my_addon.warning_message')
    });

})(Tygh, Tygh.$);

3. 翻訳ファイル

# var/langs/ja/addons/my_addon.po
msgctxt "Languages::my_addon.message_key"
msgid "English message"
msgstr "日本語のメッセージ"

CS-Cart の JavaScript イベントの一覧

イベント 説明
ce.formpre_[FORM_NAME] フォームの標準のバリデーションの前
ce.formpost_[FORM_NAME] フォームの標準のバリデーションの通過後
ce.formajaxpost_[FORM_NAME] AJAX 送信の後
ce.form_confirm 確認ダイアログの表示前
ce.commoninit 共通の初期化
ce.ajaxdone AJAX の完了後
ce.ajax_callback_[NAME] 特定の AJAX コールバック
ce.dialogshow ダイアログの表示後
ce.notificationshow 通知の表示後
ce.loadershow ローダーの表示時
ce.scrolltoelm 要素へのスクロール時
ce.switch_[ID] スイッチの切り替え時
ce.picker_js_action_[TARGET_ID] ピッカーのアクション時
ce.colorpicker.show カラーピッカーの表示時
ce.colorpicker.hide カラーピッカーの非表示時

参考

関連ページ

ナビゲーション

検索語を入力してください…

↑↓ 移動↵ 開くEsc 閉じる