Nuxt.jsで作ったサイトをNetlifyにデプロイしてフォーム機能を実装したので、その方法をまとめて見ました。
UIフレームワークにはVuetify、フォームのバリデーションにはVeeValidateを使用しています。
フォームのpostには、axiosを使用します。
完成イメージは下記の画像になります。
VeeValidateをインストール
まずは、フォームのバリデーションの為にVeeValidateをインストールします。
# npm
npm install vee-validate --save
# yarn
yarn add vee-validate
pluginsディレクトリにてVeeValidateの設定
├─ plugins
│ ├─ veeValidate.js
import Vue from 'vue'
import {
extend,
ValidationProvider,
ValidationObserver,
localize
} from 'vee-validate'
import ja from 'vee-validate/dist/locale/ja.json'
import { required, email, max } from 'vee-validate/dist/rules'
localize('ja', ja)
extend('required', required) // 入力必須項目
extend('email', email) // アドレス用
extend('max', max) //最大入力数
Vue.component('ValidationProvider', ValidationProvider)
Vue.component('ValidationObserver', ValidationObserver)
nuxt.config.jsで読み込む
export default {
plugins: [{ src: '~/plugins/veeValidate.js' }]
}
フォームを作成
<template>
<div class="form">
<ValidationObserver
ref="observer"
v-slot="{ invalid, validated }"
@submit.prevent="validateForm"
tag="form"
name="contact"
method="post"
netlify <!--netlifyの設定-->
data-netlify-honeypot="bot-field" <!--netlifyの設定-->
>
<!--netlifyの設定--><input type="hidden" name="form-name" value="contact" /> <!--netlifyの設定-->
<div class="form__wrapper">
<ValidationProvider v-slot="{ errors }" name="Name" rules="required|max:20">
<v-text-field
v-model="name"
:error-messages="errors"
label="Name"
type="text"
name="name"
></v-text-field>
</ValidationProvider>
</div>
<div class="form__wrapper">
<ValidationProvider v-slot="{ errors }" name="Email" rules="required|email">
<v-text-field
v-model="email"
:error-messages="errors"
label="E-mail"
type="email"
name="email"
></v-text-field>
</ValidationProvider>
</div>
<div class="form__wrapper">
<ValidationProvider v-slot="{ errors }" name="Contact" rules="required">
<v-textarea
label="Contact"
:error-messages="errors"
v-model="text"
name="text"
></v-textarea>
</ValidationProvider>
</div>
<div class="form__wrapper">
<ValidationProvider v-slot="{ errors }" name="check" rules="required">
<v-checkbox
v-model="checkbox"
:error-messages="errors"
label="送信しますか?"
type="checkbox"
value="1"
class="checkbox"
></v-checkbox>
</ValidationProvider>
</div>
<!--netlifyの設定-->
<div v-show="false">
<label for="message">スパム対策</label>
<input type="text" name="bot-field" v-model="botField" />
</div>
<!--netlifyの設定-->
<v-btn @click="clearForm">リセット</v-btn>
<v-btn type="submit">送信</v-btn>
</ValidationObserver>
</div>
</template>
<script lang="ts">
import Vue from 'vue'
export default Vue.extend({
data() {
return {
name: '',
email: '',
text: '',
checkbox: null,
botField: '',
}
},
methods: {
//バリデーション用のメソッド
validateForm() {
const observer: any = this.$refs.observer
const result = await observer.validate()
if (!result) {
return
}
//バリデーションを通過すればsubmitForm()を呼び出す
this.submitForm()
},
//次の章で追加
submitForm() {
},
//クリア用のメソッド。リセットボタンを押すとフォームを空白に戻します。
clearForm() {
const observer: any = this.$refs.observer
this.name = ''
this.email = ''
this.text = ''
this.checkbox = null
observer.reset() //バリデーションをリセット
}
}
})
</script>
<!--netlifyの設定-->
と記述した部分はNetlifyとの連携部分になります。
NetlifyのFormのドキュメント
@submit.prevent
とすることで、submitをするのをストップしています。
@submit.prevent="validateForm"
でメソッドを呼び出して、axiosでフォームをpostする為です。
axiosでnetlifyにフォームを送信する
<script lang="ts">
import Vue from 'vue'
import axios from 'axios'
export default Vue.extend({
data() {
return {
name: '',
email: '',
text: '',
checkbox: null,
botField: ''
}
},
methods: {
async validateForm() {
const observer: any = this.$refs.observer
const result = await observer.validate() //バリデーションのチェック。入力されていない項目があれば、処理を止める
if (!result) {
return
}
this.submitForm()
},
async submitForm() {
const params = this.setParams()
const response: any = await axios.post('/', params).catch((error) => {
error.response
})
},
//送信する項目をセット。
setParams() {
const params = new URLSearchParams()
params.append('form-name', 'contact')
params.append('name', this.name)
params.append('email', this.email)
params.append('text', this.text)
if (this.botField) {
params.append('bot-field', this.botField)
}
return params
}
})
</script>
new URLSearchParams()
を使い、フォームの内容をセットしています。
そして、axiosでpostを実行しています。
送信が完了すれば、スナックバーでお知らせする機能を追加
Vuetifyのスナックバーを使って、送信が上手く行った場合にポップアップでお知らせをする機能を追加します。
<template>
<div class="form">
<!-- 省略 -->
<!-- 追加 -->
<v-snackbar v-model="completeForm" timeout="3000" vertical color="primary"> <!-- 送信成功時 -->
送信を完了しました。
<template v-slot:action="{ attrs }">
<v-btn text v-bind="attrs" @click="completeForm = false">
Close
</v-btn>
</template>
</v-snackbar>
<v-snackbar v-model="errorForm" timeout="5000" vertical color="error"> <!-- 送信エラー時 -->
送信でエラーが発生しました。
<template v-slot:action="{ attrs }">
<v-btn text v-bind="attrs" @click="errorForm = false">
Close
</v-btn>
</template>
</v-snackbar>
<!-- 追加 -->
</div>
</template>
<script lang="ts">
import Vue from 'vue'
import axios from 'axios'
export default Vue.extend({
data() {
return {
name: '',
email: '',
text: '',
checkbox: null,
botField: '',
completeForm: false,
errorForm: false
}
},
methods: {
async validateForm() {
const observer: any = this.$refs.observer
const result = await observer.validate()
if (!result) {
return
}
this.submitForm()
},
async submitForm() {
const params = this.setParams()
const response: any = await axios.post('/', params).catch((error) => {
error.response
//エラーだった場合は、エラー用のスナックバーを表示
this.errorForm = true
})
//送信が完了した後の処理を追加
if (response.status === 200) {
this.completeForm = true
this.clearForm()
} else {
//エラーだった場合は、エラー用のスナックバーを表示
this.errorForm = true
}
}
})
</script>
最後に
Nuxt.jsとNetlifyの組み合わせはかなり便利ですね。ホスティングも簡単ですし、フォーム機能も使いやすいです。