- Date
Google FormをカスタマイズHTMLからFetch APIで送信する方法
- Share on Hatena
- Share on X
- Share on Facebook
目次
HTML で埋め込むメリット・デメリット メリット デメリット HTML でフォームを組む JS でフォームを送信 submit イベントにイベントリスナーを設定 URLSearchParams でパラメータの組み立て Fetch API でフォームの送信 まとめGoogle Form を カスタム HTML に埋め込み、JavaScript の Fetch API で送信する方法を紹介します。
デメリットが大きいですが、数週間など短期間なら要件次第で有用でしょう。
しかし Google Form の仕様変更で壊れるので、長期間使うならリスクが高いので避けましょう。実際に仕様変更が 2022 年にありました。
HTML で埋め込むメリット・デメリット
メリット
- カスタム HTML なので、好きなデザインのフォームを組める
- Google フォームを使っていないように見え、回答者に安心感がある
- 簡単にフォームが構築できる
デメリット
- Google フォームが公式にサポートしていないので、仕様変更で壊れる
- js でフォームを送信に失敗してもハンドリングできない
HTML でフォームを組む
こちらを参考に Google Form の input 要素の name を抽出します。
<form action="https://docs.google.com/forms/u/0/d/e/xxxxxx/formResponse" method="POST" class="google-form" > <div> <label for="email">メールアドレス</label> <input id="email" type="email" name="" placeholder="example@example.co.jp" required /> </div> <button type="submit" name="button">送信</button> </form>
JS でフォームを送信
コード全文を先に紹介します。
function submitGoogleForm(e: Event) { e.preventDefault() const urlSearchParams = new URLSearchParams() const form = e.target as HTMLFormElement const inputs = form.getElementsByTagName('input') for (let i = 0; i < inputs.length; i++) { urlSearchParams.append(inputs[i].name, inputs[i].value) } fetch(form.action, { method: form.method, mode: 'no-cors', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, body: urlSearchParams.toString(), }).then((res) => console.log(res)) } const googleForm = document.getElementsByClassName('google-form') for (let i = 0; i < googleForm.length; i++) { googleForm[i].addEventListener('submit', submitGoogleForm) }
submit イベントにイベントリスナーを設定
まず、フォームにイベントリスナーを設定し、フォーム送信時に関数が実行されるようにします。汎用性を考えてgoogle-form
というクラスをフォームにつけています。
そして関数の最初 e.preventDefault()
でフォームの内容を指定した URL へ送信するというデフォルトの動作をキャンセルします。
function submitGoogleForm(e: Event) { e.preventDefault() // 処理 } const googleForm = document.getElementsByClassName('google-form') for (let i = 0; i < googleForm.length; i++) { googleForm[i].addEventListener('submit', submitGoogleForm) }
URLSearchParams でパラメータの組み立て
URL のクエリー文字列の操作を行うURLSearchParams
インターフェイスがあるので、これを使います。直感的に key と value が追加でき、クエリー文字列に変換できます。
URLSearchParams - Web API | MDN
値を追加する方法は、URLSearchParams.append()
、URLSearchParams.set()
の 2 種類があります。
URLSearchParams.append()
は同じ key でセットしても上書きされませんが、URLSearchParams.set()
は上書きされる違いがあります。
const urlSearchParams = new URLSearchParams() const form = e.target as HTMLFormElement const inputs = form.getElementsByTagName('input') for (let i = 0; i < inputs.length; i++) { urlSearchParams.append(inputs[i].name, inputs[i].value) }
Fetch API でフォームの送信
基本的には、Google フォームと異なるドメインからフォームを送るはずです。
しかしFetch APIは、セキュリティ上の理由から同一オリジンポリシーに従います。デフォルトだと以下のようなCORS エラーでリクエストが遮断されます。
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://some-url-here. (Reason: additional information here).
そこで、モードにno-cors
を設定します。それによりCORS-safelisted methods
とCORS-safelisted request-headers
だけを使ったリクエストを送り、成功するとopaque filtered response
が返ってきます。
同一オリジンポリシーを無視してたデータが取得できるのは脆弱性に繋がるため、opaque filtered response
はデータがフィルタリングされています。type がopaque
となり、status が0
、body がnull
となり、エラーレスポンスと区別できないレスポンスになります。
body には、URLSearchParams.toString()
でオブジェクトをクエリー文字列に変換した値を設定します。
fetch(form.action, { method: form.method, mode: 'no-cors', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, body: urlSearchParams.toString(), }) }
まとめ
Google Form を カスタム HTML に埋め込み、JavaScript の Fetch API で送信することは技術的には可能です。
しかしデメリットも大きいため、きちんと理解して使いましょう。
- Share on Hatena
- Share on X
- Share on Facebook
最近の #JavaScript の記事
qiita.com
GitHub Actionsとsemantic-releaseで、自動で高品質npmパッケージを一般公開する
- Date
qiita.com