LoginSignup
5
3

More than 3 years have passed since last update.

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

Last updated at Posted at 2020-09-29

Nuxt.jsで認証認可入り掲示板APIのフロントエンド部分を構築する #5 ログイン・ログアウトの実装

はじめに

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

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

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

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

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の修正

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を定義して終わりです。

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は)初心者でお見苦しいコードも多々あったかと思いますが、これをきっかけにオリジナルのアプリケーション構築への挑戦をオススメします。

終わり

連載目次へ

5
3
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
5
3