前回までの状況はこちら。
最新ソースはこちら(gitHub)
https://github.com/takishita2nd/diet-mng
データ一覧画面にページネーション機能を追加します。
1画面に表示するデータの数を絞り、ページ切り替えによって表示するデータを切り替えるというものです。
データの数が多くなったらこういう機能も必要になると思います。
やり方は主に2つありまして、
一つは、一度すべてのデータを取得し、その後はフロント側でよしなにするパターン。
もう一つは、ページ切り替えをするごとに必要なデータを取得するパターンです。
今回は後者の方を採用しようと思います。
まずは、データ数からページ数を求める処理を作成し、ページ切り替えの機能を作成していきます。
リポジトリの実装。
public function getTotalRecord($user)
{
return $user->WeightManagements()->count();
}
count()でデータ数が取れるんですね。便利。
コントローラーの実装。
/**
* データのレコード数を取得する
*/
public function total(Request $request)
{
return response()->json(['total' => $this->weightManagement->getTotalRecord(Auth::user())]);
}
Route::post('api/weight/total', 'Weight\ApiController@total');
ページを表示したら、このAPIを使用するようにします。
created: function() {
this.updateList();
this.createPagenate();
},
methods: {
createPagenate: function() {
var self = this;
this.pagenates = [];
axios.post('api/weight/total').then(function(response){
var total = response.data.total;
self.maxPage = Math.floor(total / 10) + 1;
for(var i = 1; i <= self.maxPage; i++) {
self.pagenates.push(i);
}
}).catch(function(error){
});
},
APIでデータ数を取得し、そこからページ数とページネーションのリスト(1,2,3…)をリストで作成します。
これを使用して、テンプレートを作成します。
<div id="pagenate">
<ul>
<li>
<a href="#" v-if="prevShow" @click="prevPage()"><</a>
<b v-else><</b>
</li>
<li v-for="page in pagenates">
<a href="#" v-if="currentPage != page" @click="changePage(page)">{{ page }}</a>
<b v-else>{{ page }}</b>
</li>
<li>
<a href="#" v-if="nextShow" @click="nextPage()">></a>
<b v-else>></b>
</li>
</ul>
</div>
前のページ(<)、ページ数指定、次のページ(>)の順に表示させています。
ただ、1ページ目に場合は前のページが非活性化、最大ページのときは次のページが非活性化、あとは、現在のページと同じページへのリンクが非活性化させる必要があります。
これはv-ifで表示を切り替えています。
判定はcomputedで実装しています。
computed: {
prevShow: function() {
return this.currentPage != 1;
},
nextShow: function() {
return this.currentPage != this.maxPage;
},
},
あとは、ページをクリックしたときの処理を作成していきます。
changePage: function(page) {
this.currentPage = page;
this.updateList();
},
nextPage: function() {
this.currentPage += 1;
if(this.currentPage > this.maxPage) {
this.currentPage = this.maxPage;
}
this.updateList();
},
prevPage: function() {
this.currentPage -= 1;
if(this.currentPage <= 0) {
this.currentPage = 0;
}
this.updateList();
},
リスト更新処理も修正します。
updateList: function() {
this.datalists = [];
this.contents.page = this.currentPage;
this.param.contents = this.contents;
var self = this;
axios.post('api/weight/list', this.param).then(function(response){
response.data.dataLists.forEach(element => {
self.datalists.push({
id: element.id,
date: element.datetime,
weight: element.weight,
fat_rate: element.fat_rate,
bmi: element.bmi
})
});
}).catch(function(error){
});
}
/**
* データを取得する
*/
public function list(Request $request)
{
return response()->json(['dataLists' => $this->weightManagement->list(Auth::user(), $request->contents["page"])]);
}
public function list($user, $page = 1)
{
return $user->WeightManagements()
->orderBy('datetime', 'desc')
->skip(10 * ($page - 1))
->limit(10)
->get();
}
日付で降順に並べ替え、ページの開始から10件取得する、という処理に変更しています。
実行結果はこちら。