Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

Ajaxいいねボタンの色をキープさせたい

解決したいこと

課題でlaravelを使いインスタグラムの簡易サイトを作っています。
現在はAjax機能を搭載したいいねボタンを作成しています。
ボタンは実装したのですが画面を更新すると
いいねを押したボタンが初期化され、ボタンが元に戻ってしまいます。
データベースには登録されていますが、画面更新をするとデータベースからも削除されます。
ボタンを押し、画面を更新してもいいねボタンを押したままにするにはどうしたら良いでしょうか。
解決方法を教えて下さい。

Controller

app/Http/Controllers/LikeController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\User;

use Auth;

class LikeController extends Controller
{
    public function store($postId)
    {
        Auth::user()->like($postId);
        return 'ok!'; //レスポンス内容
    }

    public function destroy($postId)
    {
        Auth::user()->unlike($postId);
        return 'ok!'; //レスポンス内容
    }
}

Like.php

app/Models/Like.php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Like extends Model
{
    use HasFactory;
}
public function likes()
    {
        return $this->belongsToMany('App\Models\Post','likes','user_id','post_id')->withTimestamps();
    }

    //この投稿に対して既にlikeしたかどうかを判別する
    public function isLike($postId)
    {
      return $this->likes()->where('post_id',$postId)->exists();
    }

    //isLikeを使って、既にlikeしたか確認したあと、いいねする(重複させない)
    public function like($postId)
    {
      if($this->isLike($postId)){
        //もし既に「いいね」していたら何もしない
      } else {
        $this->likes()->attach($postId);
      }
    }

    //isLikeを使って、既にlikeしたか確認して、もししていたら解除する
    public function unlike($postId)
    {
      if($this->isLike($postId)){
        //もし既に「いいね」していたら消す
        $this->likes()->detach($postId);
      } else {
      }
    }
  

Routes

routes/web.php
<?php

use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

Route::get('/', function () {
    return view('welcome');
});

Auth::routes();


  // フォロー/フォロー解除を追加
  Route::post('/profile/{user}/follow', 'App\Http\Controllers\ProfilesController@follow')->name('follow');
  Route::delete('/profile/{user}/unfollow', 'App\Http\Controllers\ProfilesController@unfollow')->name('unfollow');

Route::get('/p/create','App\Http\Controllers\PostsController@create');
Route::get('/p/{post}','App\Http\Controllers\PostsController@show');
Route::post('/p','App\Http\Controllers\PostsController@store');

Route::get('/profile/{user}', 'App\Http\Controllers\ProfilesController@index')->name('profile.show');
Route::get('/profile/{user}/edit', 'App\Http\Controllers\ProfilesController@edit')->name('profile.edit');
Route::patch('/profile/{user}', 'App\Http\Controllers\ProfilesController@update')->name('profile.update');

Auth::routes();

Route::get('/home', [App\Http\Controllers\HomeController::class, 'index'])->name('home');



Route::get('/', 'App\Http\Controllers\PostsController@index')->name('posts.index');

Route::post('/like/{postId}',[App\Http\Controllers\LikeController::class,'store']);
Route::post('/unlike/{postId}',[App\Http\Controllers\LikeController::class,'destroy']);

Views

resources/views/posts/show.blade.php.php
@extends('layouts.app')

@section('content')


<div class="container">
  <div class="d-flex">
    <div class="col-8">
      <img src="/storage/{{ $post->image }}" class="w-100">
    </div>
    <div clas="col-4">
      <div>
        <div class="d-flex align-items-center">
          <div class="pe-3 ps-3">
            <img src="/storage/{{ $post->user->profile->image}}" class="rounded-circle w-100" style="max-width: 40px;">
          </div>
          <div>
            <div class="font-weight-bold">
              <a href="/profile/{{ $post->user->id }}">
                <span class="text-dark">{{ $post->user->username }}</span>
              </a> |
              <a href="#" class="ps-3">フォロー</a>
            </div>
          </div>
        </div>

        <hr>

        <p>
          <span class="font-weight-bold">
            <a href="/profile/{{ $post->user->id }}">
              <span class="text-dark ps-3">{{ $post->user->username }}</span>
            </a>
          </span> <div class="ps-3">{{ $post->caption }}</div>
        </p>

        <hr>

      </div>

      <div class="d-flex align-items-center pe-3 ps-2">
              <div onclick="like({{$post->id}})"><i class="far fa-heart like-btn" ></i></div>
              <div onclick="unlike({{$post->id}})"><i class="fas fa-heart unlike-btn" style="display:none;"></i></div>
              
      </div>

      <hr>

    </div>

  </div>
</div>

@endsection
<script src="{{ asset('js/alert.js') }}"></script>
<script src="https://code.jquery.com/jquery-3.2.1.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.3/umd/popper.min.js" integrity="sha384-vFJXuSJphROIrBnz7yo7oB41mKfc8JzQZiCq4NCceLEaO4IHwicKwpJf9c9IpFgh" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/js/bootstrap.min.js" integrity="sha384-alpBpkh1PFOepccYVYDB4do5UnbKysX5WZXm3XxPqe5iKTfUKjNkCk9SaVuEZflJ" crossorigin="anonymous"></script>

<meta name="csrf-token" content="{{ csrf_token() }}">

<link rel="stylesheet" href="{{ asset('/css/like.css')  }}" >

Javascript

public/js/alert.js
/******/ (() => { // webpackBootstrap
/******/ 	"use strict";
/******/
/******/
/******/ })()
;
function like(postId) {
  $(".like-btn").css('display','none');
  $(".unlike-btn").css('display','block');

  $.ajax({
    headers: {
      "X-CSRF-TOKEN": $('meta[name="csrf-token"]').attr("content"),
    },
    url: `/like/${postId}`,
    type: "POST",
  })
    .done(function (data, status, xhr) {
      console.log(data);
    })
    .fail(function (xhr, status, error) {
      console.log();
    });
}
function unlike(postId) {
  $(".unlike-btn").css('display','none');
  $(".like-btn").css('display','block');

  $.ajax({
    headers: {
      "X-CSRF-TOKEN": $('meta[name="csrf-token"]').attr("content"),
    },
    url: `/unlike/${postId}`,
    type: "POST",
  })
    .done(function (data, status, xhr) {
      console.log(data);
    })
    .fail(function (xhr, status, error) {
      console.log();
    });
}

$('.toggle_like').on('click', function ()
{
    //表示しているプロダクトのIDと状態、押下し他ボタンの情報を取得
    var thread_id = $(this).attr("thread_id");
    var like_val = $(this).attr("like_val");
    var button = $(this);

    if(like_val == '1'){

    $.ajax({
      headers: {
        "X-CSRF-TOKEN": $('meta[name="csrf-token"]').attr("content"),
      },
        type: 'POST',
      url: `/unlike_theme/`+thread_id,
    }).done(function(data, status, xhr) {
        // 成功時の処理
      button.attr('like_val', '0');
      button.children().attr('src', '/image/like_off.svg');
      console.log(data);

    }).fail(function(xhr, status, error) {
        // 失敗時の処理
      console.log();
    });

    } else {

    $.ajax({
      headers: {
        "X-CSRF-TOKEN": $('meta[name="csrf-token"]').attr("content"),
      },
        type: 'POST',
      url: `/like_theme/`+thread_id,
    }).done(function(data, status, xhr) {
        // 成功時の処理
          button.attr('like_val', '1');
      button.children().attr('src', '/image/like_on.svg');
      console.log(data);

    }).fail(function(xhr, status, error) {
        // 失敗時の処理
      console.log();
    });
  }
});

自分で試したこと

javascriptでのボタン切り替えをやめ、Viewで@if(Auth::user()->like($post->id))を使い表示の切り替えを試みましたが、ボタンを押すとボタンが消えてしまうだけで切り替わらりませんでした。画面の更新をしても消えたボタンは復活してしまいました。初心者で全くわからないので教えていただけると幸いです。

0

1Answer

view側表示のControlllerの処理などが情報が足りていないのですが、
以下がいいねボタン表示のロジックと仮定して回答いたします

      <div class="d-flex align-items-center pe-3 ps-2">
              <div onclick="like({{$post->id}})"><i class="far fa-heart like-btn" ></i></div>
              <div onclick="unlike({{$post->id}})"><i class="fas fa-heart unlike-btn" style="display:none;"></i></div>
              
      </div>

DBで保存されている状態をview側で判定してあげる必要があるため、
以下の感じでいかがでしょうか?

      <div class="d-flex align-items-center pe-3 ps-2">
              <div onclick="like({{$post->id}})" @if(//ユーザーがいいねしていないかの判定処理) style="display:none;" @endif><i class="far fa-heart like-btn" ></i></div>
              <div onclick="unlike({{$post->id}})" @if(//ユーザーがいいねしたかの判定処理) style="display:none;" @endif><i class="fas fa-heart unlike-btn"></i></div>
              
      </div>
0Like

Your answer might help someone💌