【Strapi併用】Nuxt.jsでAxiosを扱ってみるPOST編

【CORS対策版】Nuxt.jsでAxiosを扱ってみるGET編の続きとなっています。

一応Windowsで作って動作確認してからgitで飛ばしてラズパイでpullして動作させるということをやっています。

前回はCORS対策をしつつnuxtからaxiosを使って外部のAPIにGETしたのですが、 POSTをするとなった場合外部だといろいろとめんどうくさそうなので Strapiの勉強も兼ねてPOST用のAPIを作ってnuxtのAxiosからpostの練習をしようかなと思いました。

Strapiの導入に関しては「HeadlessCMSのStrapiに入門してみる」をご覧になってください。

項目2の「Strapiを起動してみる」までできていればOKです。

既になんかしらAPIを用意していてStrapiを使わない人は、 目次の「4」のPOST編から進めてもらったら大丈夫です。

Strapiでpostと確認用getのAPIを作ってみる

今回の目的用にpostAPIを作るついでにpostした内容を取得するためのget用APIもついでに作りましょう。

管理者Emailとパスワードでログインしたら早速APIを作っていきます。

コンテンツタイプを作ります。

既に作ってる人だとサイドバーの「プラグイン」項目にある「Content-Types-Builder」を選んで 表示された左側にある「+Create new collection type」を選択すると新しいコンテンツタイプを作成できます。

今回は疑似的なチャットを作ってみたいと思いますので、必要なのは

  • 投稿者名前
  • 投稿メッセージ

の2つの項目が必要になります。

まずDisplay Nameは「ChatLog」とでもしておきましょう。

次に必要項目として「Text」と「Rich Text」を使用します。

Textは1行でhtmlでいうところのinputのtype=textに部類されます。

RichTextはhtmlでいうところのtextareaに部類されると思います。

これで名前と本文を入力できるようになりますね。

どちらも必須フィールドとしておきましょう。

一意のフィールドに入れる必要はありません。

私はそれぞれのname属性はusernameとcommentにしました。

任意で大丈夫ですが、以降はこのnameで書いていきますのでご注意ください。

問題なく追加できたら保存を押して確定しましょう。

リスタート後にはもうAPIとして機能するようになっていると思います。

APIの公開範囲を設定する

デフォルトでは非公開になってしまっているので、 APIの作成が完了したら次は公開範囲の設定をしましょう。

サイドバーの設定から「ロールと権限」を選択して、 権限のところで先程作ったChatLogの項目で「Select all」を選択してすべてのAPIを有効にしておきましょう。

テストなので一旦すべて有効で大丈夫です。

その後画面右上にある緑色のボタンの「save」を選んで保存しましょう。

これで「http://192.168.0.11:1337/chat-logs」でアクセスできるようになります。

APIのアドレスに関しては先程「Select all」のところでアクセスしたい箇所のところの歯車マークを選んだら GETのアドレスとかが表示されます。

今回findのアドレスを見ると「chat-logs」となっていましたのでこのアドレスになります。

create(新たに投稿する際のpost)のアドレスも「chat-logs」でした。

例によってドメインの部分は自分のアドレスに置き換えてください。

現状何も無いので一旦テストでデータを挿入しておきましょう。

サイドバーのChatLogを選んで追加ができます。

追加したらステータスが「Draft」と下書きになってしまうので「Publish」で公開設定にしましょう。

これでアドレスにアクセスするとJSONデータが表示されるようになりました。

NuxtからAxiosで作ったAPIを叩いてみよう

これでローカルAPIが作成できましたのでnuxtに戻ってAPIを叩いてみましょう。

「【CORS対策版】Nuxt.jsでAxiosを扱ってみるGET編」でやったコードのAPIのアドレス部分を変更するだけです。

<template>
  <div class="container">
    <div v-show="coinDatas !== null && coinDatas !== undefined">
      <p>{{ coinDatas.length !== 0 ? coinDatas : '無し' }}</p>
    </div>
    <div v-show="coinDatas === null || coinDatas === undefined">
      <p>GETボタンを押してください</p>
    </div>
    <button @click="asyncData()">GET</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      coinDatas: [],
    }
  },
  methods: {
    async asyncData() {
      // APIのURL
      const url = 'http://192.168.0.11:1337/chat-logs'
      // リクエスト(Get) 非同期で取得したデータが配列で返ってくる
      const res = await this.$axios.$get(url)
      // 配列をjson形式にして返す
      this.coinDatas = res
      // return this.coinDatas
    },
  },
}
</script>

CORS対策中ではありますが、アドレスが絶対アドレスとなっているのでプロキシを挟まずアクセスしていますので CORS対策しなくても問題なく動いてくれました。

LAN内だとIPが違ってもCORSに阻まれることはなさそうですね。

さきほどテストで入力したデータのJSONが画面に表示されたら成功です。

[ { "id": 1, "username": "管理者", "comment": "これはテストメッセージだ", "published_at": "2021-03-05T03:13:29.857Z", "created_at": "2021-03-05T03:12:55.680Z", "updated_at": "2021-03-05T03:13:29.900Z" } ]

私はこんな感じにでました。

NuxtからAxiosで作ったAPIを叩いてみよう:POST編

やっとこさ本記事の本編に入ります。

まずはnuxt側からPOSTするために入力フォームを作ってやりましょう。

getはgetで残しておきたいので、post用の新たなページを作ります。

同じ階層に「axiospost.vue」とでも名付けて新規ファイルを作成してください。

<template>
  <div class="container">
    <dl v-for="(chatlog, index) in chatLogs" v-bind:key="chatlog.id">
      <dt>No.{{ index }} 名前:{{ chatlog.username }}</dt>
      <dd>{{ chatlog.comment }}</dd>
    </dl>
    <form>
      <input
        type="text"
        name="username"
        value=""
        v-model="chatDatas.username"
      />
      <textarea name="comment" v-model="chatDatas.comment"></textarea>
    </form>
    <button @click="asyncPost()">POST</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      chatDatas: {
        username: '',
        comment: '',
      },
      chatLogs: [],
    }
  },
  methods: {
    // GET用メソッド
    async asyncGet() {
      // APIのURL
      const url = 'http://192.168.0.11:1337/chat-logs'
      // リクエスト(Get) 非同期で取得したデータが配列で返ってくる
      const res = await this.$axios.$get(url)
      // 配列で返ってくるので要素を追加しておく
      this.chatLogs = res
    },

    // POST用メソッド
    async asyncPost() {
      // APIのURL
      const url = 'http://192.168.0.11:1337/chat-logs'
      // リクエスト(Get) 非同期で取得したデータが配列で返ってくる
      const res = await this.$axios.$post(url, this.chatDatas)
      // チャットログリストに追加して描写する
      this.chatLogs.push(res)
      // 入力フォームをクリア
      this.chatDatas = { username: '', comment: '' }
    },
  },
  created() {
    // 開始時にGETしておく
    this.asyncGet()
  },
}
</script>

わかりやすいようにpostとgetでメソッドを分けています。

vueの構文に関しては省略します。

処理の流れとしては生成されたときにgetメソッドが走ってdlタグの中に名前とメッセージが描写されます。

その後、値を入力してpostを押すとAPIにpostが飛びデータが追加された後に、 配列にそのログが追加されて画面に表示されるというわけです。

現状、バリデーションもなにもしてないのでpostを押すと空文字列のデータが飛んでいきます。

中身が必須にしたのに何故飛んでしまうかと言うと、 単純に「空の文字列」というものが入っているので飛んじゃうわけですね。

postする前にメソッドが呼び出されたら空文字チェックとかを本来はしたほうがいい感じです。

PHPであればサーバー側で処理もできますが、HeadlessCMSに関しては 基本的に単純なCRUD処理のみだけになります。

Strapiの設定次第ではpostされた値が空のとき~とかの設定もできるかもしれませんが、 まだそこまでStrapiに詳しくないので今はなんとも言えません。

postしちゃうと通信が発生するので、それならjavascript側で精査しておけば無駄な通信をへらすこともできるので 基本的にバリデーションはフロント側でやったほうがいいと私は思っています。

さて、これで擬似チャットが出来上がりました。

後は見た目整えてバリデーションをきっちりして データベースをnosqlとかmysqlとかに変えてきっちり管理すればアプリケーションとしては出来上がると思います。

nuxt&Strapi入門としてはここまでになります。

次回はnuxtやstrapiなどを使ってブログシステムを構築していこうかなと思います。

実用性があるかどうかはわかりませんが、脱Wordpressを目指して自作ブログシステムを作りたいですね。