KurocoとNuxt.jsで、コンテンツ一覧ページにページネーションを実装する

コンテンツの数が多い場合、コンテンツ一覧を複数のページに分割するページネーションの実装が必要になる場合があります。
Kurocoのトピックスリストのエンドポイントは、レスポンスに記事数・現在のページ・ページ数の合計 などが含まれるため、フロント側でページ数の計算をすることなくページネーションの実装が可能です。

本チュートリアルではKurocoとNuxt.jsで、コンテンツ一覧ページを作成するで作成したコンテンツ一覧ページ(お知らせ一覧)にページネーションを実装する方法を説明します。

このページはKurocoとNuxt.jsでのプロジェクトが構築済みであり、コンテンツ一覧のページが作成されていることを前提としています。
まだ構築していない場合は、下記のチュートリアルを参照してください。
Kurocoビギナーズガイド
KurocoとNuxt.jsで、コンテンツ一覧ページを作成する

APIの設定

APIの登録内容はKurocoとNuxt.jsで、コンテンツ一覧ページを作成すると同じです。
こちらで作成したAPIをそのまま利用する場合はKurocoで1ページ当たりの表示数を設定に進んでください。

API基本設定を行う

まずはAPIの登録をします。
Kurocoの管理画面から[API]->[Default]をクリックします。
Image from Gyazo

[追加]をクリックします。
Image from Gyazo

タイトル、版、ディスクリプションを入力して[追加する]をクリックします。
Image from Gyazo

追加したAPIに遷移しますので、続いて、セキュリティの設定をします。
[セキュリティ]をクリックします。
Image from Gyazo

[Cookie]を選択して[保存する]をクリックします。
fetched from Gyazo

注意)
Cookieをセキュリティ用のトークンとして利用する場合、APIドメインとフロントエンドのドメインが違うとサードパティクッキーの問題があり、Safari等で認証が効きません。
フロントエンドとAPIドメインをサブドメイン違いで設定をする必要があるので、独自ドメイン/TLS証明書でAPIドメインを設定し、アカウント設定からAPIドメインを変更ください。
(Chromeでは正常に動作しますので、開発やテストの段階ではまずChromeで構築していただくことをお勧めします。)

CORS設定を行う

[CORSを設定する] をクリックします。

Image from Gyazo

CORS_ALLOW_ORIGINSの [Add Origin] をクリックし、下記を追加します。

  • http://localhost:3000/
  • フロントエンドドメイン

CORS_ALLOW_METHODSの [Add Method] をクリックし、下記を追加します。

  • GET
  • POST
  • OPTIONS

CORS_ALLOW_REDENTIALSの[Allow Credentials]にチェックが入っていることを確認します。

Image from Gyazo

問題なければ [保存する] をクリックします。

エンドポイントを設定する

次にエンドポイントを作成します。今回は下記エンドポイントを作成します。

  • お知らせ一覧エンドポイント
  • お知らせ詳細エンドポイント

お知らせ一覧

お知らせ一覧エンドポイントを下記設定にて作成します。

項目設定内容
パスnews
カテゴリーコンテンツ
モデルTopics
オペレーションlist
topics_group_idお知らせを登録しているコンテンツ定義ID

Image from Gyazo Image from Gyazo Image from Gyazo

設定完了後、「追加する」をクリックします。

お知らせ詳細

お知らせ詳細エンドポイントを下記設定にて作成します。

項目設定内容
パスnewsdetail
カテゴリーコンテンツ
モデルTopics
オペレーションdetails
topics_group_idお知らせを登録しているコンテンツ定義ID

Image from Gyazo Image from Gyazo Image from Gyazo

設定完了後、「追加する」をクリックします。

Kurocoで1ページ当たりの表示数を設定する

1ページ当たりのコンテンツ表示数は固定になるため、Kurocoの管理画面側でパラメータの設定をします。 エンドポイントに表示するページの情報をパラメータとして渡すことで、各ページのレスポンスを得ていきます。

お知らせ一覧のエンドポイントを作成したAPIのページに遷移します。
Image from Gyazo

お知らせ一覧のエンドポイント(今回の場合は /rcms-api/7/news)の[更新]をクリックします。
Image from Gyazo

エンドポイントの設定画面が開くので、基本設定のcntに1ページ当たりの表示数を入力します。今回は4と入力し[更新]をクリックします。
Image from Gyazo

Swagger UIで各ページの情報が取得できることを確認する

次にエンドポイントからのレスポンスを確認します。
「お知らせ一覧」のエンドポイントを作成したAPIのページに遷移します。
Image from Gyazo

[Swagger UI]をクリックします。
Image from Gyazo

「お知らせ一覧」のエンドポイントの[Try it out]をクリックします。
Image from Gyazo

pageIDに1を入力します。
Image (fetched from Gyazo)

[Execute]をクリックします。
Image (fetched from Gyazo)

レスポンスを確認すると1ページ目の4件のリストと、pageInfoの情報が確認できます。
Image from Gyazo

同様にpageIDにページ数を入力して[Execute]をクリックすると、各ページのリストと、pageInfoのレスポンスが得られます。
こちらを利用してフロントでページネーションを実装してきます。

現在のページ情報をパラメータで指定する

現在のページの情報をパラメータに追加し、各ページに対応するレスポンスを得ます。
以下の内容でindex.vueファイルと、_slug.vueを作成します。

/pages/news_list/index.vue
<template>
  <div>
    <p>ニュース一覧ページ{{ this.$route.query.page }}</p>
    <div v-for="n in response.list" :key="n.slug">
      <nuxt-link :to="`/news_list/${n.topics_id}`">
        {{ n.ymd }} {{ n.subject }}
      </nuxt-link>
    </div>

  </div>
</template>

<script>
export default {
  async asyncData({ $axios, route }) {
    return {
      response: await $axios.$get('/rcms-api/7/news', {
        params: {
          pageID: route.query.page || 1,
        },
      }),
    };
  },
};
</script>
/pages/news_list/_slug.vue
<template>
  <div>
    <h1 class="title">{{ response.details.subject }}</h1>
    <div class="post" v-html="response.details.contents"></div>
  </div>
</template>

<script>
export default {
  async asyncData({ $axios, params }) {
    return {
      response: await $axios.$get(`/rcms-api/7/newsdetail/${params.slug}`),
    };
  },
};
</script>

/rcms-api/7/news/rcms-api/7/newsdetailの部分はご自身のエンドポイントのURLに変更してください。
以下同様に、ソースコード内のエンドポイントURLはご自身のエンドポイントURLに変更をお願いします。

クエリパラメータに?page=2を追加すると、表示されるお知らせの一覧が変更されることを確認できます。
Image from Gyazo

ページ遷移のためのリンクを表示する

次にページを遷移するためのリンク部分を作成します。
エンドポイントからのレスポンスのpageInfoに現在のページ数や最終ページの情報が含まれるので、こちらを利用します。
ここでは簡単な例としてindex.vueファイルを以下のように修正します。
また、リンクの記述部分は流用できるようcomponentsフォルダにPagenator.vueのファイルを作成し、こちらに記述します。

index.vueを下記のように変更します。

/pages/news_list/index.vue
diff --git a/pages/news_list/index.vue b/pages/news_list/index.vue
index 9afa0782..769c615c 100644
--- a/pages/news_list/index.vue
+++ b/pages/news_list/index.vue
@@ -7,6 +7,7 @@
       </nuxt-link>
     </div>

+    <Pagenator v-bind="{ ...response.pageInfo }" />
   </div>
 </template>

components/Pagenator.vueを下記のように作成します。

/components/Pagenator.vue
<template>
  <ul>
    <li>
      <nuxt-link
        :to="{
          path: $route.path,
          query: { page: pageNo - 1 },
        }"
        @click.native="$nuxt.refresh"
        :class="{ disabled: ($route.query.page || 1) <= 1 }"
      >
        前へ
      </nuxt-link>
    </li>

    <li v-for="i in totalPageCnt" :key="i">
      <nuxt-link
        :to="{ path: $route.path, query: { page: i } }"
        @click.native="$nuxt.refresh"
        :class="{
          disabled: pageNo === i,
        }"
      >
        {{ i }}
      </nuxt-link>
    </li>
    <li v-if="pageNo === totalPageCnt">次へ</li>
    <li v-else>
      <nuxt-link
        :to="{
          path: $route.path,
          query: { page: pageNo + 1 },
        }"
        :class="{
          disabled: totalPageCnt === $route.query.page,
        }"
        @click.native="$nuxt.refresh"
      >
        次へ
      </nuxt-link>
    </li>
  </ul>
</template>

<script>
export default {
  props: {
    pageNo: {
      required: true,
      type: Number,
    },
    totalPageCnt: {
      required: true,
      type: Number,
    },
  },
};
</script>

<style scoped>
ul {
  list-style: none;
  display: flex;
}

.disabled {
  pointer-events: none;
  cursor: default;
  text-decoration: none;
  color: black;
}
</style>

各ページへのリンクが追加できました。
Image from Gyazo

以上で、KurocoとNuxt.jsで、コンテンツ一覧ページにページネーションを実装する方法の説明を終わります。

お探しのページは見つかりましたか?解決しない場合は、問い合わせフォームからお問い合わせいただくか、Slackコミュニティにご参加ください。