ハウツー:Ajax送信
XHR/Ajax でフォームを送信
フォーム処理のデフォルトのメカニズムは、 HTML 標準のフォーム送信によっており、 HTML フォームは、 POST
または GET
(デフォルトは POST
)でサーバーに送られます。送られたフォームは、 バリデーション され、 処理 された後に、結果がフォームに送り返され(もしくは、 リダイレクトされたページへ遷移し )、メッセージが表示されたり、必要に応じて再送信するための編集ができたりします。
これは、ページのリロードを伴うため、ときどき、望ましくないこともあります。このような場合、 Ajax や XHR を使った JavaScript 経由で、フォームを送信することがより良い選択になります。幸運なことに、 Grav のフォーム機能は、このタスクに対応しています。
自動的なアプローチ(From プラグイン `v7.3.0` 以上)
Form プラグインのバージョン 7.3.0
のリリースにより、XHR によるフォーム送信機能が、素早いセットアップオプションで利用可能になりました。XHR により、フォームのその場所での処理となり、ページ全体のリロードは不要になります。
これを有効にするには、単純に、このオプションを Form のブループリントに追記するだけです:
xhr_submit: true
action:
や、 template:
、 id:
さえ設定する必要はありません。1ページに複数の ajax フォームがあったとしても、プラグインは ‘機能’ します。これは、新しい form-xhr.html.twig
テンプレートを使い、 vanilla JS(ライブラリを利用しないJavaScript)コードでリクエストを行います。
[!Info]
このアプローチでは、 XHR を使って、フォーム全体を送信し、フォームの HTML 全体をレスポンスで書き換えます。これはシンプルなアプローチですが、必要に応じて独自の高度なソリューションを作成できます。
[!Tip]
XHR リクエストに使用される JavaScript コードは、form/layouts/xhr.html.twig
にあります。必要であれば、これを あなたのテーマのtemplates
フォルダに(パス構造を維持しながら)コピーし、必要な修正をほどこしてください。
手動のアプローチ(Form プラグイン `v7.3.0` 未満)
フォームを作成する
お好みで、標準的なフォームを作り、それを利用できます。今回の例では、Ajax 制御部分にフォーカスするため、できるだけシンプルなものにしています。まず、 forms/ajax-test/
フォルダに、 form.md
というページを作成します:
---
title: Ajax Test-Form
form:
name: ajax-test-form
action: '/forms/ajax-test'
template: form-messages
refresh_prevention: true
fields:
name:
label: Your Name
type: text
buttons:
submit:
type: submit
value: Submit
process:
message: 'Thank you for your submission!'
---
ご覧の通り、これはとても基本的なフォームで、シンプルに名前を尋ねて、送信ボタンが提供されます。目立っているのは、 template: form-messages
の部分だけです。 フロントエンドのフォーム セクションで解説したとおり、フォーム処理の結果を表示するためにカスタムの Twig テンプレートを提供できます。これは、フォームを処理し、 Ajax 経由でメッセージを返し、ページに注入するための素晴らしい方法です。フォームプラグインには、これを実現する form-messages.html.twig
テンプレートがすでに用意されています。
[!Note]
ここでは、action: '/forms/ajax-test'
をハードコーディングして使用しています。そのため、 Ajax は固定の URL を持ち、現在のページルーティングにアクションを設定するわけではありません。これは、 Ajax リクエストがリダイレクトを適切に制御しない問題を解決します。これをしておかないと、 ‘home’ ページなどで、問題が起こりえます。ハードコーディングするのは、現在のフォームページである必要はなく、ただ固有で、到達可能なルーティングでありさえすれば良いです。
ページコンテンツ
この同じページに、少しの HTML と、 JavaScript を追加する必要があります:
<div id="form-result"></div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const form = document.querySelector('#ajax-test-form');
form.addEventListener('submit', function(event) {
event.preventDefault();
const result = document.querySelector('#form-result');
const action = form.getAttribute('action');
const method = form.getAttribute('method');
fetch(action, {
method: method,
body: new FormData(form)
})
.then(function(response) {
if (response.ok) {
return response.text();
} else {
return response.json();
}
})
.then(function(output) {
if (result) {
result.innerHTML = output;
}
})
.catch(function(error) {
if (result) {
result.innerHTML = 'Error: ' + error;
}
throw new Error(error);
});
});
});
</script>
<div id="form-result"></div>
<script>
$(document).ready(function(){
var form = $('#ajax-test-form');
form.submit(function(e) {
// prevent form submission
e.preventDefault();
// submit the form via Ajax
$.ajax({
url: form.attr('action'),
type: form.attr('method'),
dataType: 'html',
data: form.serialize(),
success: function(result) {
// Inject the result in the HTML
$('#form-result').html(result);
}
});
});
});
</script>
まず、 div タグのプレースホルダを定義します。 ID は#form-result
で、フォームの結果を注入する場所として利用します。
ここでは、簡単のため jQuery 構文を使用していますが、同じような機能を実行するものならば、お好きな JavaScript を使うことができます。まず、フォームのデフォルトの submit アクションを止めて、 Ajax でフォームのデータをシリアライズしながらアクションを呼び出します。この呼び出しに対する結果は、先に作成した div タグに戻ります。