Nuxt3を利用した問い合わせフォームに確認画面を追加する

最終更新日:

Table of contents

このチュートリアルでは、Newtの Form AppNuxt3 を利用して作成された問い合わせフォームに、確認画面を追加する手順を紹介します。
VeeValidate を利用して、実装します。

記事内で使用している主なソフトウェアのバージョン

  • Nuxt(nuxt): 3.10.3
  • VeeValidate(vee-validate): 4.12.6

前提条件

  • Nuxt3を利用した問い合わせフォームを作成済みであること

Nuxt3を利用した問い合わせフォームの作成方法について知りたい場合は、以下のドキュメントをご確認ください。

概要

Nuxt3で作成した問い合わせフォームに、入力内容の確認画面を追加します。
※ ここではスタイルについては扱いません。

実装としては、ページ内で状態を管理し、入力用の画面と確認用の画面を出し分けます。

作成される問い合わせフォームは以下のようになります。

1. 基本のフォーム

もともと、以下のような問い合わせフォームがあるとします。
基本的な問い合わせフォームの作成方法について知りたい場合は、NewtとNuxt3を利用して、問い合わせフォームを作成する のドキュメントをご確認ください。

pages/contact.vue
1<script lang="ts" setup>
2import { useForm } from 'vee-validate'
3
4const config = useRuntimeConfig()
5
6const { defineField, handleSubmit } = useForm()
7const [name, nameProps] = defineField('name')
8const [email, emailProps] = defineField('email')
9const [message, messageProps] = defineField('message')
10
11const onSubmit = handleSubmit(async (values) => {
12  const formData = new FormData()
13  Object.entries(values).forEach(([key, value]) => {
14    formData.append(key, value)
15  })
16
17  try {
18    const response = await fetch(config.public.newt.formEndpoint, {
19      method: 'POST',
20      body: formData,
21      headers: {
22        Accept: 'application/json'
23      }
24    })
25
26    if (response.ok) {
27      await navigateTo('/thanks')
28    } else {
29      await navigateTo('/error')
30    }
31  } catch (err) {
32    await navigateTo('/error')
33  }
34})
35
36useHead({
37  title: 'Newt・Nuxtフォーム',
38  meta: [
39    { name: 'description', content: 'NewtとNuxtを利用した問い合わせフォームです' }
40  ]
41})
42</script>
43
44<template>
45  <div>
46    <h1>Contact us</h1>
47    <form @submit="onSubmit">
48      <label for="name">Name</label>
49      <input id="name" v-model="name" v-bind="nameProps" name="name">
50      <label for="email">Email</label>
51      <input id="email" v-model="email" v-bind="emailProps" name="email" type="email">
52      <label for="message">Message</label>
53      <textarea id="message" v-model="message" v-bind="messageProps" name="message" />
54      <button type="submit">
55        Submit
56      </button>
57    </form>
58  </div>
59</template>

2. 確認画面の追加

2-1. 状態の定義

入力用の画面と確認用の画面を出し分けるために isInput という変数を定義します。
この isInputtrue の場合は入力用の画面を表示し、false の場合は確認用の画面を表示します。

pages/contact.vue
<script lang="ts" setup>
import { useForm } from 'vee-validate'

const config = useRuntimeConfig()
const isInput = useState(() => true)

(省略)

2-2. 確認画面の追加

pages/contact.vue を以下のように修正します。
ポイントは以下の通りです。

  • 「Confirm」ボタンの押下時に、isInputfalse にする
  • 「Back」ボタンの押下時に、isInputtrue にする
  • isInput の値で入力画面と確認画面を出し分ける

※ 下記ではフォームの送信結果に応じて、/thanks または /error にリダイレクトしていますが、ここでは詳細は扱いません。興味のある方は、NewtとNuxt3を利用して、問い合わせフォームを作成する のチュートリアルをご確認ください。

pages/contact.vue
1<script lang="ts" setup>
2import { useForm } from 'vee-validate'
3
4const config = useRuntimeConfig()
5const isInput = useState(() => true)
6
7const { defineField, handleSubmit } = useForm()
8const [name, nameProps] = defineField('name')
9const [email, emailProps] = defineField('email')
10const [message, messageProps] = defineField('message')
11
12const onConfirm = () => {
13  isInput.value = false
14}
15
16const goBack = () => {
17  isInput.value = true
18}
19
20const onSubmit = handleSubmit(async (values) => {
21  const formData = new FormData()
22  Object.entries(values).forEach(([key, value]) => {
23    formData.append(key, value)
24  })
25
26  try {
27    const response = await fetch(config.public.newt.formEndpoint, {
28      method: 'POST',
29      body: formData,
30      headers: {
31        Accept: 'application/json'
32      }
33    })
34
35    if (response.ok) {
36      await navigateTo('/thanks')
37    } else {
38      await navigateTo('/error')
39    }
40  } catch (err) {
41    await navigateTo('/error')
42  }
43})
44
45useHead({
46  title: 'Newt・Nuxtフォーム',
47  meta: [
48    { name: 'description', content: 'NewtとNuxtを利用した問い合わせフォームです' }
49  ]
50})
51</script>
52
53<template>
54  <div v-if="isInput">
55    <h1>Contact us</h1>
56    <label for="name">Name</label>
57    <input id="name" v-model="name" v-bind="nameProps" name="name">
58    <label for="email">Email</label>
59    <input id="email" v-model="email" v-bind="emailProps" name="email" type="email">
60    <label for="message">Message</label>
61    <textarea id="message" v-model="message" v-bind="messageProps" name="message" />
62    <button type="button" @click="onConfirm">
63      Confirm
64    </button>
65  </div>
66  <div v-else>
67    <h1>Please confirm your submission</h1>
68    <form @submit="onSubmit">
69      <table>
70        <tbody>
71          <tr>
72            <th>Name</th>
73            <td>{{ name }}</td>
74          </tr>
75          <tr>
76            <th>Email</th>
77            <td>{{ email }}</td>
78          </tr>
79          <tr>
80            <th>Message</th>
81            <td>{{ message }}</td>
82          </tr>
83        </tbody>
84      </table>
85      <div>
86        <button type="button" @click="goBack">
87          Back
88        </button>
89        <button type="submit">
90          Submit
91        </button>
92      </div>
93    </form>
94  </div>
95</template>

これで http://localhost:3000/contact にアクセスすると、まず以下のようなフォームが表示されます。
nuxt3-form-confirm1.png

フォームに内容を入力し、「Confirm」ボタンを押すと、以下のように表示されます。
nuxt3-form-confirm2.png

「Back」を押すと入力画面に戻り、「Submit」を押すとフォームが送信されることが確認できます。

NewtMade in Newt