Help us understand the problem. What is going on with this article?

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

きっかけ

どこかのサイト:「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とは意味合いが異なります。 

shozzy
個人開発やってます(dispbarcode.com)。Web系のシステム開発とデータ連携が得意。
https://shozzy.netlify.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした