以前実装したリアルタイムチャット機能に編集と削除機能を追加しました。
目次
大まかな流れ
1, routeの設定
2, コントローラーの設定
3, vue側でモーダル表示
4, axiosでコントローラーに送信
以下を削除も同じ流れで実装します
routeの設定
まずはrouteの設定から。resourceで設定してしまえばオッケーです。
詳細なリンクはphp artisan route:listで確認できます。
Route::resource('message', 'MessageController');
vue側でモーダル表示
編集ボタンをクリックしたらモーダルが表示されるようにします。
dataにfalseでモーダルを用意、cssを記述。message_editクリックでモーダルが表示される。という流れになっています。
モーダルではedit_messageに対して編集を加えていきます。message_updateがクリックされたらedit_messageを持ってaxiosでコントローラーに飛んでいくようにしています。
backメソッドは”モーダルは開いたけど、編集はしなかった”という時に使います。以前のmessageの状態を取得、表示しているのです。
<div v-for="message in array" :key="message.id">
<p class="small text-muted edit" @click="message_edit(message)">編集</p>
</div>
// モーダルエリア
<div id="edit" v-if="showmodal" @click="back(edit_message)">
<div id="i" @click.stop>
<div class="bg-primary rounded py-2 px-3 mb-2">
<input type="text" v-model="edit_message.text">
<button type="button" class="btn btn-primary btn-sm" @click="message_update(edit_message)">編集</button>
</div>
</div>
</div>
・・省略
data() {
return {
showmodal: false,
edit_message: {}
}
}
・・省略
message_edit(message) {
this.edit_message = message
// 編集前のtextデータを入れておく。編集しないで戻ってきた時用
this.edit_message.back_text = message.text
// モーダル発火
this.showmodal = true
},
message_update(message) {
this.showmodal = false
let link = ["http://127.0.0.1:8000/message/", message.id];
let path = link.join('')
axios.put(path, message).then(res => {
console.log(res.data)
}).catch(function(error){
console.log(error)
})
},
back(message) {
this.showmodal = false
// 編集が無い時にback_textで編集前の状態に戻す
this.edit_message.text = message.back_text
}
・・省略
#edit {
/*要素を重ねた時の順番*/
z-index:1;
/*画面全体を覆う設定*/
position:fixed;
top:0;
left:0;
width:100%;
height:100%;
background-color:rgba(0,0,0,0.5);
/*画面の中央に要素を表示させる設定*/
display: flex;
align-items: center;
justify-content: center;
}
コントローラーの設定
まずは編集から。$requestで変更されたメッセージを受け取れるようにしています。if文で作成者であればupdateの処理に進みます。
updateが実行されたら、pusherに変更点を伝えたいのでeventを発火させています。これでリアルタイムで編集が実行されます。
public function update(Request $request)
{
$message = Message::findOrFail($request->id);
$user = Auth::user();
$message->text = $request->text;
if($request->user_id === $user->id) {
$message->update();
event(new MessageCreated($message)); 以前の記事で説明しています
return $message;
} else {
return false;
}
}
削除
削除は比較的新しいことはしないので、コントローラーもvueもまとめて書きます。
vue側でしていることは、削除するメッセージを持ってaxiosでコントローラーに飛ばす。うまく行ったらfilterを使ってvue側で削除しています。
updateの時みたいにevent発火させるやり方が上手くいかなかったので、この方法にしました。
<div v-for="message in array" :key="message.id">
<p class="small text-muted delete" @click="message_delete(message)">削除</p>
</div>
・・省略
data() {
return {
array: []
}
},
・・省略
message_delete(message) {
let link = ["http://127.0.0.1:8000/message/", message.id];
let path = link.join('')
axios.delete(path, message).then(res => {
// 削除が出来たらvue側で削除する。別々で動いてる
this.array = this.array.filter(ele => ele.id !== message.id)
}).catch(function(error){
console.log(error)
})
}
public function destroy(Request $request)
{
$delete_message = Message::findOrFail($request->message);
$delete_message->delete();
}
ポイント
axiosで飛ばす時は一緒に情報も飛ばしてあげる。
また、その時のアクションによってaxiosにputやdeleteといったものをつける。
削除の場合はvue側でfilterを使ってリアルタイムにしている。
backメソッドを作ってモーダルを開いても編集しないで戻ってきた時に備える。以前の情報を表示できるようにする。
まとめ
難しいところは特に無いかなと思います。
個人的には削除もpusher経由で出来るだろ〜と思っていますが、今回はvue側で処理することにしました。w
次は階層式のカテゴリー機能とか、転移式のユーザー登録とか実装してみたいな〜とか思ってます!
そんな感じで
以上!