7
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Nuxt+VuetifyなSPAから、Netlify Formsを使う方法。

Last updated at Posted at 2020-02-09

#きっかけ
どこかのサイト:「Netlify Formsを使うと、フォーム機能を手軽に作成できます。」

自分:「なるほど。やってみよう。」

Nuxt+Vuetifyで作ったSPAにお問い合わせフォームをつけようとする)

自分:「わからん。ズバリなサンプルコードも見つからん。:innocent:

自分:「自力で開拓するしかないな...」

#環境
vue@2.6.11 nuxt@2.11.0 vuetify@2.1.4

#プレーンなHTMLの場合
プレーンなHTMLから Netlify Forms にPOSTする仕組みの作り方は、formタグにnetlify属性をつけるだけ。
例えば以下のようなHTMLを書いてNetlifyにアップ1すると、これを自動的に解析してPOSTできるようにしてくれます。

sample.html
<!-- 抜粋 -->
    <form name="contact" method="POST" netlify>
      <input type="text" name="name" />
      <input type="text" name="email" />
      <input type="text" name="company" />
      <textarea name="message"></textarea>
      <button type="submit">送信</button>
    </form>

たったこれだけ。お手軽ですね!

でも、自分が作りたいのはNuxtベースのSPAなんです。しかもVuetifyを適用。単純には行きません...

#Nuxt+Vuetifyの場合
次のことがわかっていないので、どうにか解決する必要があります。

  1. どうやってNetlifyにフォームの存在とその内容(項目)を伝えるか
  2. VuetifyのフォームからPOSTするときにフォームデータをどのように取り扱うか

ひとつずつ見ていきます。

##1. どうやってNetlifyにフォームの存在とその内容(項目)を伝えるか

ダミーのHTMLを使います。このこと自体はNetlifyの公式ブログにも載っています。
ただ、Nuxtでの方法までは書いてありません。どこのフォルダに置くかとか。

Vue単体での事例やReactでの事例などを参考にさせていただきつつ試行錯誤した結果、以下のようにすればOKということがわかりました。

  • Nuxt の static フォルダ配下にHTMLを配置
  • 名前は任意でよいので、今回はdummy-contact-form.htmlにしました。
  • form要素はname属性とnetlify属性が重要。action属性やmethod属性は不要。
  • hidden属性をつけておくとhtmlを直接表示してもなにも見えないのでいい感じ。2
static/dummy-contact-form.html
<!DOCTYPE html>
<html>
  <body>
    <!-- 完全にダミーフォーム専用 -->
    <form name="contact" netlify netlify-honeypot="bot-field" hidden>
      <input type="text" name="name" />
      <input type="text" name="email" />
      <input type="text" name="company" />
      <textarea name="message"></textarea>
      <input type="text" name="bot-field" />
    </form>
  </body>
</html>

これをNetlifyにアップすると、Formsが生成されます。

スクリーンショット 2020-02-09 21.37.29.png
netlify-honeypot について 上記例では、botよけとして`netlify-honeypot="bot-field"`の設定も入れました。 これは、netlify-honeypot属性で指定した項目名のフォーム(ここでは`bot-field`)に何か入力があったら、それはbotの投稿とみなして投稿がブロックされます。 Forms の Spam submissions にすら入りません。

##2. Nuxt+VuetifyからPOSTするときにフォームデータをどのように取り扱うか
Nuxt(SPA)からのPOSTなのでaxiosを使ってJavaScriptから非同期で投稿します。
また、Vuetifyを使っているので、inputではなくv-text-fieldtextareaではなくv-textareaを使うことになります。3

具体的には、以下のようにしました。

  • form-nameに、ダミーフォームのform.nameと同じ内容を設定する
  • 各項目の名前もダミーフォームと一致させる
  • params.appendするときの名前が一致していればOKです。
pages/contact.vue
<template>
  <!-- 抜粋です -->
  <v-text-field
    v-model="name"
    label="お名前"
    required
  />
  <v-text-field
    v-model="email"
    label="メールアドレス"
    required
  />
  <v-text-field
    v-model="company"
    label="会社名(法人の方のみ)"
  />
  <v-textarea
    v-model="message"
    label="お問い合わせ内容"
    required
  />
  <v-text-field
    v-model="botfield"
    label="人間は入力しないでください"
    v-show="false"
  />
  <v-btn color="primary" @click="submit">送信</v-btn>
</template>

<script>
export default {
  data() {
    return {
      name: "",
      email: "",
      company: "",
      message: "",
      botfield: "",
    }
  },
  methods: {
    async submit() {
      const params = new FormData()
      //以下、ダミーフォームの各フォーム要素のnameと合わせる
      params.append('form-name', 'contact')
      params.append('name', this.name)
      params.append('email', this.email)
      params.append('company', this.company)
      params.append('message', this.message)
      params.append('bot-field', this.botfield)

      const response = await this.$axios.$post(window.location.origin, params)
      //実際はresponseを使って画面側にフィードバックさせるが、ここでは仮にconsoleに出力
      console.log(response)
    },
  },
}
</script>

※実際はresponseを使って画面側にフィードバックさせる必要がありますが、ここでは仮にconsoleに出力するだけにしています。また、バリデーションのコードも必要になるでしょう。

##結果
画面はこのようになりました。(適当な値を入力したあとのキャプチャです)
スクリーンショット 2020-02-09 23.15.23.png

送信したところ、投稿した内容もちゃんとFormsに入りました:tada:
スクリーンショット 2020-02-09 23.31.59.png

#まとめ
Nuxt+Vuetify な SPA から、 Netlify Forms を使うときの対応方法。

  1. static配下にプレーンなHTMLでダミーフォームを作成し、Netlifyにフォームの存在を認識させる。
  2. そのフォームと項目を一致させる形で、axiosからFormDataを投げる。

#余談
この仕組みを作るとき、axiosのbaseURL関係でもハマりました。
上記コードでしれっとthis.$axios.$post(window.location.origin, params)と書いているところ。
それについては別の記事を書こうと考えています。書きました。(2020.02.12)

#参考
https://www.netlify.com/blog/2018/09/07/how-to-integrate-netlify-forms-in-a-vue-app/
https://qiita.com/yahsan2/items/a70c4c8f617ee9b1f9ff
https://qiita.com/miiina016/items/e86c0bf4f8808dd6b6ae
https://qiita.com/nanaki14/items/007eae905d6305f75f6a
https://qiita.com/tatane616/items/f646e84fe4cdd9eac0de

  1. Netlifyと連携してあるGitHubのリポジトリにpush

  2. もちろんデベロッパーツールを使えばHTMLの中身は見えます。それも避けるなら、Netlify側でリダイレクトの設定を入れておけば良いようです。

  3. ちなみに、v-formはフォームのバリデーションを手軽に実装するためのコンポーネントなので、通常のformとは意味合いが異なります。

7
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?