前提・実現したいこと
ここに質問の内容を詳しく書いてください。
現在laravelとJavascript(Vue.js)を使ってチャットのウェブアプリを作成しています。
LINEなどのように、下から上にスクロールすると古いチャットの内容が出てくるようにしたいので、vue.jsのinfinite-loading機能を使って、古いデータを表示したいです。
自分の意図としては、
まずroomメソッドによって、最新の35件がチャットルーム表示される。
スクロールしたら、main.jsの
axios.get(`/member/${room.dataset.memberId}/fetch` ``` によって、web.php の ```ここに言語を入力 Route::get('/member/24/fetch', 'App\Http\Controllers\ChatsController@fetch')->name('fetch');
がfetchメソッドを呼び出す。
そしてfetchメソッドの
$chats = Chat::getData($member,$request->beforeId);
によってscrollメソッドにbeforeIdが渡され、scrollメソッドが呼び出され、beforeIdより古い10件のチャットデータを持つ$chatsという配列がreturnされることで、
fetchメソッド内の$chatsという配列にbeforeIdより古いチャットデータが入る。
そのデータがJson形式でmain.jsに送られ、foreachの処理によってもともと画面に映っていたchatのデータに後ろから追加されていく。
という感じです。
発生している問題・エラーメッセージ
エラーが出ているわけではないのですが、最上部までスクロールしてもinfinite-loadingが起動しないです。
該当のソースコード
room.blade.php
<div class="chat-container row justify-content-center" id="room" data-member-id="{{$member->id}}" data-chats="{{json_encode(array_values($messages->all()))}}" style="width:100%;overflow-y:scroll;position:absolute;bottom:200px;top:56px;margin:0;padding:0;height:75vh;"> <div class="chat-area" class="col-md-8 offset-md-2"> <infinite-loading @infinite="fetchChats" spinner="default" direction="top"></infinite-loading> <div v-for="chat in chats"> @{{ chat.body }} </div> </div> </div>
該当のソースコード
main.js
Vue.config.devtools = true; import Vue from 'vue'; import InfiniteLoading from 'vue-infinite-loading'; // ライブラリの読み込み Vue.component('infinite-loading', InfiniteLoading); // コンポーネント化 const room=document.getElementById('room'); // $(function() { // getNewData(); // }); new Vue({ el: '#room', data:{ page: 0, chats: JSON.parse(room.dataset.chats) }, methods: { fetchChats($state) { // console.log(`/member/${room.dataset.memberId}/fetch`); axios.get(`/member/${room.dataset.memberId}/fetch`, { params: { beforeId: this.chats[0].id, page: this.page } }) .then(response => { if (response.data.chats.length) { this.page++; response.data.chats.forEach (value => { this.chats.unshift(value); }); $state.loaded(); } else { $state.complete(); } }) .catch(error => { console.log(error); }) }, } });
該当のソースコード
chatController.php
public function room(Member $member) { if(Auth::user()->id > $member->id){ $room=Room::where([ ['member1_id', '=', Auth::user()->id], ['member2_id', '=', $member->id] ])->first(); }else{ $room=Room::where([ ['member1_id', '=', $member->id], ['member2_id', '=', Auth::user()->id] ])->first(); } $limit = 35; $messages = Chat::where('room_id', '=', $room->id) ->with('member') ->orderBy('created_at', 'desc') ->take($limit) ->get(); $messages = $messages->sortBy('created_at'); return view('chat.room', compact('member','room','messages')); } public function fetch(Member $member,Request $request) { $chats = Chat::getData($member,$request->beforeId); return response()->json(['chats' => $chats], 200); }
該当のソースコード
Chat.php
public static function getData(Member $member,$beforeId){ if(Auth::user()->id > $member->id){ $room=Room::where([ ['member1_id', '=', Auth::user()->id], ['member2_id', '=', $member->id] ])->first(); }else{ $room=Room::where([ ['member1_id', '=', $member->id], ['member2_id', '=', Auth::user()->id] ])->first(); } $limit = 10; // 一度に取得する件数 $chats = Chat::where('room_id', '=', $room->id) ->where('id', '<',$beforeId) ->with('member') ->orderBy('created_at', 'desc') ->take($limit) ->get(); if (is_null($chats)) { return []; } return $chats; }
該当のソースコード
web.php
Route::as('chats.')->middleware('auth')->group(function () { Route::get('/member/{member}/room', 'App\Http\Controllers\ChatsController@room')->name('room'); Route::get('/member/{member}/fetch', 'App\Http\Controllers\ChatsController@fetch')->name('fetch'); Route::get('/member/{member}/getData', 'App\Http\Controllers\ChatsController@getData')->name('getData');
試したこと
画面の高さを飛び出たら自動的に表示されるスクロールバーではなく、room.blade.phpで自分でheightを設定して、スクロールバーを表示しているため、自分で設定したスクロールバーとinfinite-loadingが紐ずいていないのかと思いました。そこで、hrightとoverflow-y:scrollを消して画面の高さを飛び出すと自動的に表示されるスクロールバーで試してみたのですが、結局infinite-loadingは実行されませんでした。
補足情報(FW/ツールのバージョンなど)
laravel:8.13.0, vue.js:2.6.12
あなたの回答
tips
プレビュー