Nuxt.jsで認証認可入り掲示板APIのフロントエンド部分を構築する #6 記事投稿フォームの作成

←[Nuxt.jsで認証認可入り掲示板APIのフロントエンド部分を構築する #5 ログイン・ログアウトの実装](https://qiita.com/rf_p/items/b714298e1f9effa32cad)

# はじめに

今回はNuxt編の最終回。
記事投稿フォームをindexに設置します。

ログインしていないと書き込めないので、ログイン中のみフォームを表示します。

# Railsのレスポンスコード修正

まず下準備として、Rails側の修正漏れ箇所を直します。
postのsave失敗時、ステータスが200(正常)で返ってきてしまっておりエラーがキャッチできないので、レスポンスコードを422で返すようにします。

```diff:app/controllers/v1/posts_controller.rb
...
       if post.save
         render json: post
       else
-        render json: { errors: post.errors }
+        render json: { errors: post.errors }, status: 422
       end
     end
...
       if @post.update(post_params)
         render json: @post
       else
-        render json: { errors: @post.errors }
+        render json: { errors: @post.errors }, status: 422
       end
     end
...
```

postした時にNuxt側でtry catchを使っていますが、エラーが出てもレスポンスコードが200だとcatchブロックに行きません。ここは以前の設定ミスなのであらかじめ塞いでおきます。

# pages/index.vueとstore/index.jsの修正

```diff:pages/index.vue
       sm8
       md6
     >
+      <form v-if="logged_in" @submit.prevent="newPost">
+        <v-card>
+          <v-card-title class="headline">
+            新規投稿
+          </v-card-title>
+          <v-card-text>
+            <ul v-if="errors">
+              <li v-for="(message, key) in errors" :key="key">
+                {{ key }}
+                <span v-for="(m, i) in message" :key="i">
+                  {{ m }}
+                </span>
+              </li>
+            </ul>
+            <v-text-field
+              id="subject"
+              v-model="subject"
+              label="subject"
+              name="subject"
+              prepend-icon="mdi-subtitles"
+            />
+            <v-textarea
+              id="body"
+              v-model="body"
+              label="body"
+              name="body"
+              prepend-icon="mdi-comment-text"
+            />
+          </v-card-text>
+          <v-card-actions>
+            <v-spacer />
+            <v-btn color="primary" type="submit">
+              投稿
+            </v-btn>
+          </v-card-actions>
+        </v-card>
+      </form>
       <v-card v-for="post in posts" :key="post.id">
         <v-card-title class="headline">
           <n-link :to="`/posts/${post.id}`">
...
 <script>
 export default {
+  data () {
+    return {
+      subject: '',
+      body: '',
+      errors: []
+    }
+  },
   computed: {
     posts () {
       return this.$store.getters['posts/posts']
+    },
+    logged_in () {
+      return this.$store.getters.logged_in
+    }
+  },
+  methods: {
+    async newPost () {
+      try {
+        await this.$store.dispatch('posts/newPost', {
+          subject: this.subject,
+          body: this.body
+        })
+        this.subject = ''
+        this.body = ''
+        this.errors = []
+      } catch (e) {
+        this.errors = e.data.errors
+      }
+      const posts = await this.$store.dispatch('posts/fetchPosts')
+      this.$store.commit('posts/setPosts', posts.posts)
     }
   }
 }
```

エラーメッセージの表示箇所や、投稿後のposts再取得あたりがやっつけ感満載ですが。
やっていることはログインフォーム等と大差無いですね。

最後にstore/posts.jsにnewPostを定義して終わりです。

```diff:store/posts.js
 export const actions = {
   async fetchPosts () {
     return await this.$axios.$get('/v1/posts')
+  },
+  async newPost (_c, post) {
+    return await this.$axios.$post('/v1/posts', post)
   }
 }
```

# 終わりに

今回でNuxt.js編最終回です。
Rails編からご覧いただいていた場合、18+6で24章にも及ぶ連載です。ご覧いただいたり、プログラムを書いていただいた皆様ありがとうございました。

Railsで実装したCRUD処理でNuxt側未実装の点も多いため、ここからは自力で実装に挑戦してみてください。

また、RailsもNuxtも（特にNuxtは）初心者でお見苦しいコードも多々あったかと思いますが、これをきっかけにオリジナルのアプリケーション構築への挑戦をオススメします。

# 終わり

【[連載目次へ](https://qiita.com/rf_p/items/0277ae96c5de433b4849#%E7%9B%AE%E6%AC%A1)】