search
LoginSignup
26

More than 1 year has passed since last update.

posted at

updated at

Organization

楽勝すぎるはずの netlify form を nuxt generate で頑張って使う

netlify form が楽勝すぎる

netlify は静的ファイルのホスティングサービスだが、フォームを簡単に埋め込むことができる。

受託制作において、これまで簡単なフォームを埋め込むために PHP が動く環境で動かしていたので、
netlify を使えば、簡単に組み込む事ができて便利。

詳細はドキュメントを見ていただければと思うが、 <form> タグに netlify の属性を追加するだけで、あとは通常どおり netlify 上で build して deploy すれば、なんとフォームが使えるようになる。

vue
<form name="contact" method="POST" netlify>
  <p>
    <label>Your Name: <input type="text" name="name" placeholder="新垣結衣"></label>   
  </p>
  <p>
    <label>Your Email: <input type="email" name="email" placeholder="yui@aragaki.love"></label>
  </p>
  <p>
    <label>Message: <textarea name="message" placeholder="新垣結衣のホームページをつくりたいです。など"></textarea></label>
  </p>
  <p>
    <button type="submit">Send</button>
  </p>
</form>

しかも、csv でダウンロードできるし、Slack に飛ばすことができるし、楽勝で form が使えます。

やっぱり netlify 好きです。

nuxt generate だと、全然楽勝じゃない、、

ただ、上記 html を vue コンポネントの template 書いて、nuxt generate したファイルを netlify に上げてもうまくいかなかった。

具体的には、下記のエラーが developer tools の console に出た。

[nuxt] Error while initializing app DOMException: Failed to execute 'appendChild' on 'Node': This node type does not support this method.
    at Object.appendChild

これは、生成された html と component を利用してレンダリングをする html が異なる場合に、エラーになるっぽい。(多分)

また、<nuxt-link> での dom書き換えによる遷移後も、エラーがでないものの通常のPOSTのフォームの挙動となり、正常に動作しなかった。

原因

そこで、netlify にホスティングされた生成された html をみると、

vue
<form name="contact" method="POST">
  <input type="hidden" name="form-name" value="contact">
  <p>
    <label>Your Name: <input type="text" name="name" placeholder="新垣結衣"></label>   
  </p>
  <p>
    <label>Your Email: <input type="email" name="email" placeholder="yui@aragaki.love"></label>
  </p>
  <p>
    <label>Message: <textarea name="message" placeholder="新垣結衣のホームページをつくりたいです。など"></textarea></label>
  </p>
  <p>
    <button type="submit">Send</button>
  </p>
</form>

<input type="hidden" name="form-name" value="contact"> が追加されていることがわかった。

build するときに、html をパースして、type="hidden"の input を差し込んでくれているみたい。

そしてそのとき合わせて POST のAPIを作ってくれることで、静的ホスティングサービスなのに、フォームが実現できるようだった。

だが、nuxt で作られるコンポーネントの dom は、この置換がされていないので、通常のフォームの挙動になってしまうし、nuxt が予期せぬ html があるということでエラーが出てしまっているのが原因っぽい。

解決策

まず console のエラーをなくす解決策として、 <no-ssr> <client-only> タグを使うことで、generate する HTMLを無くして、ズレをなくした。

※追記 2020/02/05 <no-ssr>は、nuxt3 から deprecated みたいなので、<client-only>のが良さそうです。

vue
<client-only>
<form name="contact" method="POST">
  <input type="hidden" name="form-name" value="contact">
  <p>
    <label>Your Name: <input type="text" name="name" placeholder="新垣結衣"></label>   
  </p>
  <p>
    <label>Your Email: <input type="email" name="email" placeholder="yui@aragaki.love"></label>
  </p>
  <p>
    <label>Message: <textarea name="message" placeholder="新垣結衣のホームページをつくりたいです。など"></textarea></label>
  </p>
  <p>
    <button type="submit">Send</button>
  </p>
</form>
</client-only>

すると無事エラーはとれた。※ type="hidden"の input は含めたままにする。

追記 2020/02/05現在 ダミーを作らなくても API を生成してくれるようになったみたいです。
@kkotaro0111 さん情報ありがとうございます。

が!これではパースされる html がないので、今度はフォームのPOST APIが作られずに、通常の タグが埋め込まれるだけになってしまう。

次に、static/form.html を用意し、form.html

form.html
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title>おといあわせ</title>
  <link rel="stylesheet" href="">
</head>
<body>
  <form name="contactform" method="post" netlify >
    <input name="name" type="text" class="input is-success" placeholder="新垣結衣">
    <input type="email" name="email" class="input is-success"  placeholder="yui@aragaki.love">
    <textarea name="message" class="textarea" placeholder="新垣結衣のホームページをつくりたいです。など"></textarea>
  </form>
</body>
</html>

とnuxt generate とか関係ないダミーの html を用意し、build 時に POST API を作らせるようにした。
ちなみに、このパースされたフォーム内にある input の name 属性しか、paramで投げても受け入れてくれないので、 .vue と input の数や属性は、揃える必要があった。

また一応このあたりで、リダレクトをかけることでダミーにはアクセスできないようにもできる。
https://www.netlify.com/docs/redirects/

こうすることで、なんとか nuxt generate で生成したファイルでも 頑張って netlify form 使うことに成功した。

が、頑張って使ってて、全然スマートじゃないので、なんかいい方法あれば教えてください。

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
What you can do with signing up
26