2020-02-19追記
現時点ではGoogleForm側の仕様変更により、下記手順では出来なくなっています。
そもそもGoogleが推奨しているやり方ではない(と私は認識しています)ので、告知なく仕様の変更が行われ、機能しなくなる恐れがあります。
Googleの推奨する、GoogleAPIを利用したSpreadSheetへのレコード追加や、NetlifyFormなど、その他の手段を利用してフォームを作ることをオススメいたします!
やりたいこと
コーポレートやLPなどの案件の時、たまにこういう時あります。
Next.js & Nowや、Nuxt.js & Netlifyなどの構成で、サーバーレスで構築してね
あ、でもなんらかの形でFormは作ってね!
うーん、なんか簡単にできないかな
色々実現方法はあると思います
-
Netlify Form
- Netlify利用ならあっという間にできます。
- こちらの記事にめっちゃ詳しく乗ってます。今回は取り扱いません。
-
GoogleForm
- 単純にリンク貼るだけでも、機能としては必要十分ですね。
「ただちょっとコーポレートとかで使うには、
ザ GoogleForm
って見た目がねえ。。」
やったこと
フォーム機能はGoogleFormに乗っかりつつ、フロントは作ってPOSTで通信する
はじめに
TypeScriptを一部入れてます。実際は.tsx
です。Snippetが対応していないのか赤線出てるので.jsx
にしてます。
1. GoogleFormの用意
2. POST通信に必要なパラメーターを確認
-
DevelomentToolsなどでソースを表示し、各フォームの値がどのようなparamでやりとりしているか確認しましょう。
3. 集めた情報をソースにまとめておく
オブジェクトとして、一つのファイル(.js
や.tsx
など)にまとめておきしょう。
export const ContactGoogleForm = {
action:
'https://docs.google.com/forms/u/0/d/e/1FAIpQLSdCgDgog4LTBHSwuSliZwa9Q7mEt7dSZypREwDEJXVFmQvOvg/formResponse',
name: 'entry.1902046290',
gender: 'entry.1524608684',
inquiry: 'entry.1741685192',
}
4. フロントコーディング
ここは楽しいところですね。いい感じに仕上げましょう必要ならUIフレームワークなども利用しましょう。
import React from 'react'
import styled from 'styled-components'
const StyledTable = styled.table`
width: 100%;
table-layout: fixed;
`
const TextArea = styled.textarea`
margin-top: 10px;
width: 100%;
height: 100px;
`
const Th = styled.th`
padding-top: 10px;
`
const StyledSubmit = styled.button`
border: 1px solid #000;
display: block;
padding: 18px 90px;
font-size: 16px;
margin: 10px auto 0;
color: #000;
`
const StyledInput = styled.input`
width: 100%;
border: solid 1px #000;
padding: 4px;
box-sizing: border-box;
font-size: 16px;
`
const options: string[] = ['男性', '女性', '回答しない']
export const ContactForm: React.FC<any> = () => {
return (
<form>
<StyledTable>
<tbody>
<tr>
<Th>
<p>お名前</p>
</Th>
<td>
<StyledInput type={'text'} name={'name'} />
</td>
</tr>
<tr>
<Th>
<p>性別</p>
</Th>
<td>
{options.map((option) => (
<div key={option}>
<label>
<input type={'radio'} name={'gender'} value={option} />
{option}
</label>
</div>
))}
</td>
</tr>
</tbody>
</StyledTable>
<p>お問い合わせ内容</p>
<TextArea name={'inquiry'} />
<StyledSubmit type={'submit'}>送信する</StyledSubmit>
</form>
)
}
5. データ連携(ReactHookForm利用)
今回は、超簡単にFormを生成できるReactHookFormを利用しました。
色々と便利に利用できますが、今回は以下の通り最低限利用しました。
- Formの
onSubmit
にhandleSubmit
と関数を渡す - 各Inputに
ref={register()}
を追加
import React from 'react'
import styled from 'styled-components'
// react-hook-form
import { useForm, Controller } from 'react-hook-form'
// 先ほど取得したGoogleForm関連データ
import { ContactGoogleForm } from '@/constants/ContactGoogleForm'
// axios
import axios from 'axios'
// ~~~ 中略 ~~~
export const ContactForm: React.FC<any> = () => {
const { register, handleSubmit } = useForm({
mode: 'onChange',
})
return (
<>
<form noValidate onSubmit={handleSubmit(submit)}>
<StyledTable>
<tbody>
<tr>
<Th>
<p>お名前</p>
</Th>
<td>
<StyledInput type={'text'} name={'name'} ref={register()} />
</td>
</tr>
<tr>
<Th>
<p>性別</p>
</Th>
<td>
{options.map((option) => (
<div key={option}>
<label>
<input
type={'radio'}
name={'gender'}
value={option}
ref={register()}
/>
{option}
</label>
</div>
))}
</td>
</tr>
</tbody>
</StyledTable>
<p>お問い合わせ内容</p>
<TextArea name={'inquiry'} ref={register()} />
<StyledSubmit type={'submit'}>送信する</StyledSubmit>
</form>
</>
)
}
const submit = (values) => {
console.log(values)
}
6. axiosを使ってPOST通信
// axios
import axios from 'axios'
// 先ほど作成したGoogleFormの情報
import { ContactGoogleForm } from '@/constants/ContactGoogleForm'
// ~~~~ 中略 ~~~~
const submit = (values) => {
// ReactHookFormは、hundleSubmitに渡した関数に、
// registerを利用して登録した各Inputの値をObjectとして渡されてくる。
// values.nameやvalues.genderと呼び出せる。便利ですね!
const GOOGLE_FORM_ACTION = ContactGoogleForm.action
// CORS対策は必須
const CORS_PROXY = 'https://cors-anywhere.herokuapp.com/'
// PostのParm生成
const submitParams = new FormData()
submitParams.append(ContactGoogleForm.name, values.name)
submitParams.append(ContactGoogleForm.gender, values.gender)
submitParams.append(ContactGoogleForm.inquiry, values.inquiry)
// 実行
axios
.post(CORS_PROXY + GOOGLE_FORM_ACTION, submitParams)
.then(() => {
window.location.href = '/thanks' // 成功時
})
.catch((error) => {
console.log(error) // 失敗時
})
}
ちゃんと、GoogleFormに飛んでますね!
(参考) Slack通知を実現
感想
これはこれで簡単に見た目作れるので、ミニマムでいいですよね。
Formとしての機能はGoogleFormで今回の用途としては必要十分でした。