---
title: "フォームの送信イベントとバリデーション"
description: "ce.formpre_ と ce.formpost_ の使い分け、バリデーション通過後の非同期処理、JavaScript での翻訳の使い方。"
---

> Documentation Index
> Fetch the complete documentation index at: https://docs.cs-cart.jp/llms.txt
> Use this file to discover all available pages before exploring further.

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

フォームの送信の前後にカスタム処理を追加する方法です。追加のバリデーション、確認ダイアログ、送信データの加工、外部 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` 属性のないフォームは、フックできません。

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

## 基本の書き方

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

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

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

})(Tygh, Tygh.$);
```

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

```javascript
$.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 の値
});
```

## 使用例

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

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

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

```javascript
$.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; // 送信をキャンセル
    }
});
```

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

```javascript
$.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" />');
});
```

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

```javascript
['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_ の中で ceFormValidator('check') を使わない**
>
> `ce.formpre_` の中で `$.ceFormValidator('check')` を呼んでも、`undefined` が返り、結果を使えません。

### 悪い例：`ce.formpre_` を使う

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

### 良い例：`ce.formpost_` を使う

```javascript
// バリデーションを通過した後に発火する
$.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)` を使います。

```javascript
$(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', ...)` を使います。

```javascript
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`

```smarty
<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 で翻訳を取得する

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

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

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

})(Tygh, Tygh.$);
```

### 3. 翻訳ファイル

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

> **翻訳を使うときの注意**
>
> * `|escape:"javascript"` を付け忘れると、引用符で JavaScript の構文エラーになります。
> * JS ファイルを読み込むより先に、`_.tr({...})` を実行する必要があります。
> * 登録していないキーは、空文字を返します。
> * `$.ceFormValidator('check')` は、エラーの表示も自動で行います。

## 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` | カラーピッカーの非表示時 |

## 参考

* [CS-Cart 公式ドキュメント：Microformats](https://docs.cs-cart.com/latest/developer_guide/core/front-end/microformats.html)（英語）
* [Javascript hooks used in CS-Cart 4.x](https://forum.cs-cart.com/t/javascript-hooks-used-in-cs-cart-4-x/55503)（CS-Cart 公式フォーラム、英語）

## 関連ページ

* [マイクロフォーマット](/core/shop-front/microformats/forms/)
* [フォームに独自のバリデーターを追加する](/addon-development/tips/custom-form-validator/)
* [フォームのクラスに関する注意点](/addon-development/tips/form-classes/)

Source: https://docs.cs-cart.jp/addon-development/tips/form-events-and-validation/index.mdx
