Google Form連携

## はじめに
Webサイトで必要となる機会が多いFormですが、バックエンドを実装するのは面倒です。
Google Formを使うと便利ですが、デザインはサイトにマッチしないでしょう。
デザインはHTML, CSSで作成し、裏側をGoogle Formで作成することができます。

同じような内容の記事は複数存在しますが、 jQueryが使われていたり、サクセスページがGoogleデフォルトのものもあります。
当記事では、バニラJSでGoogle Formにデータを送信する方法に注目し、JavaScriptの処理を公開します

## 構築方法
詳しい構築方法は他の記事やブログが写真付きで紹介してくれています。
そちらも参照してみてください
他記事で紹介されていないアドバイスを1つ加えると、3のnameを探す際に、google formに仮のデータを入れることで、検証ツールから探しやすくなります。また、formのactionを探す際にactionで探すのではなく<formで探すとすぐに見つかります。
```
1 Google Formを作成
2 HTMLでFormを作成
3 actionと各inputのnameをhtmlのformにコピー
4 valueが必要な要素はvalueもコピー
4 送信できることを確認したのちjsの処理を追加し最終確認
```

## 注意点
この点を紹介していない記事が多いのですが、特にcheckboxのvalueは忘れがちです。
わかりやすいエラーも出てこないため、見落とすと解決まで時間がかかるかもしれません
valueもgoogle formを検証ツールで確認して、確実につけましょう
```
selectはselectタグにのみnameを付与
optionはvalueをgoogle formに合わせる

radioはnameを全て一緒にする

checkboxはnameだけではなくvalueもgoogle formに合わせて付与する必要がある
```

## 留意点
この留意点が自作のメール機能の開発コストをpayできるかで実装するかどうかを決めてください
```
fetch後に返されるstatusは常に0 (下記2点の場合ユーザー側は送信に失敗していることに気づけない)
1 google側のサーバーが死んでいる場合 (滅多にない)
2 誤ってGoogle Formを削除した場合 (管理側が間違えなければ問題ない)

Wi-Fi(ネットワーク)非接続状態の検知はtry{}catch(){}で可能
カフェのFree Wi-Fiで1時間経過後通信が遮断されたタイミングで送信ボタンが押された場合に検知できる

submit buttonを無効化しているので、ブラウザデフォルトのバリデーションも無効化されている
```

## 追加で実装すべきこと
当記事はGoogle FormにバニラJSでfetchすることに重きを置いているので、この辺は省略します。
```
ネットワーク非接続状態の検知をするためのtry{}catch(){}
valudation機能(デフォルトでは送信ボタンをdisabledにする)
thanksページやsuccessメッセージ
```
## コード
google formで作成したものにあわせてください
formとbuttonにはidを付与しています。
nameやvalueの付け方は下記を参考にしてください
```html
<form action="google formのaction" id="form" method="post">
  <label>
    名前
    <input type="text" name="entry.959761466" />
  </label>
  <label>
    メールアドレス
    <input type="email" name="entry.47493665" />
  </label>
  <label>
    性別
    <input type="radio" name="entry.905341941" value="男性" />男性
    <input type="radio" name="entry.905341941" value="女性" />女性
    <input type="radio" name="entry.905341941" value="女性" />回答しない
  </label>
  <label>
    種別
    <select name="entry.1969064209">
      <option value="エンジニア">エンジニア</option>
      <option value="デザイナー">デザインナー</option>
    </select>
  </label>
  <label>経歴
    <textarea name="entry.1889375747"></textarea>
  </label>
  <label>
    <input
      type="checkbox"
      name="entry.1928974007"
      value="個人情報の取り扱いに同意する"
    />
    個人情報の取り扱いに同意する
  </label>
  <button type="submit" id="button">送信する</button>
</form>
```

submit処理
```js
const form = document.getElementById("form");
const button = document.getElementById("button");

button.addEventListener("click", handleSubmit);

function handleSubmit(e) {
  e.preventDefault();

  fetch(form.action, {
    method: "POST",
    body: provideUrlEncodedFormData(form),
    mode: "no-cors",
    headers: {
      "Content-Type": "application/x-www-form-urlencoded",
    },
  });
  // 送信後の処理を記述...
}

// requestのbodyに合うようにurlencodeしたformの入力内容を提供
function provideUrlEncodedFormData(form) {
  const formData = new FormData(form);
  return new URLSearchParams(Object.fromEntries(formData.entries())).toString();
}
```


```js
// provideUrlEncodedFormDataを簡略化した処理
// 上記のものと一緒ですが、理解する際の参考にしてください
// 見慣れないWeb APIを使っていると思います。 公式ドキュメントがわかりやすいです
function provideUrlEncodedFormData(form) {
  const formData = new FormData(form);
  const formDataObject = {};

  for (const [key, value] of formData.entries()) {
    formDataObject[key] = value;
  }

  return new URLSearchParams(formDataObject).toString();
}
```

## 終わりに
過去にjQueryで実装したことがあり、それをJavaScript化すれば数分でできると思ったのですが、いろいろ試行錯誤していたら2日もかかりコードも面影すら残りませんでした。 
~~スプラトゥーンやってたせい~~
jQueryのAjaxとFetch処理は多少複雑なことをやろうとすると、コードに大きな違いが出ますね
過去に作成したjQueryには無駄な処理も含まれており、バニラJS化することができ満足です。
さよならjQuery!!

## 参考

https://developer.mozilla.org/ja/docs/Web/API/FormData

https://developer.mozilla.org/ja/docs/Web/API/URLSearchParams

https://qiita.com/ovrmrw/items/1c1564481c4ca9cc4351