Search code examples
phplaravellaravel-livewire

Modal window in Laravel Livewire component shows same information for different products on 'Buy' button click


The issue is with the modal window that opens when you click the Buy button in a Livewire component that contains multiple products. Despite the fact that each product has unique information, the modal window displays the same information regardless of which Buy button is clicked.

Here is a code snippet of the Livewire component's view:

<div>
    <!-- Products -->
    <div class="grid grid-cols-1 gap-4 mx-auto sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-3 xl:grid-cols-6">
        @foreach ($products as $product)
            <div class="w-full overflow-hidden bg-gray-900 rounded-md shadow-lg">
                <img class="object-cover w-full h-56" src="{{ $product->image }}" alt="Image">
                <div class="flex items-center justify-between px-3 py-2 bg-gray-800">
                    <p class="text-lg font-bold text-white">${{ $product->price }}</p>

                   <!-- Buy button -->
                    <button class="btn btn-sm" wire:click="openModal({{ $product->id }})" wire:loading.attr="disabled"
                        wire:target="openModal({{ $product->id }})">Buy</button>
                   <!-- -->

                </div>
            </div>
        @endforeach
    </div>
  <!-- -->

<!-- Modal window  -->
<div class="fixed inset-0 z-10 {{ $showModal ? 'visible' : 'hidden'  }} overflow-y-auto">
    <div class="flex items-center justify-center min-h-screen px-4">
      <div class="fixed inset-0 transition-opacity">
        <div class="absolute inset-0 bg-gray-500 opacity-75"></div>
      </div>
      <div class="overflow-hidden transition-all transform bg-white rounded-lg shadow-xl sm:max-w-lg sm:w-full">
        <div class="px-4 py-3 text-lg font-medium text-gray-800 bg-gray-100">{{ $product->name }}</div>
        <div class="p-4">
          <p class="text-gray-700">{{ $product->description }}</p>
        </div>
        <div class="px-4 py-3 bg-gray-100 sm:flex sm:flex-row-reverse">
          <button class="w-full px-4 py-2 mb-2 font-bold text-white bg-blue-500 rounded sm:w-auto sm:mb-0 sm:mr-2 hover:bg-blue-700">
            Save
          </button>
          <button wire:click='closeModal()' class="w-full px-4 py-2 font-bold text-gray-800 bg-gray-400 rounded sm:w-auto hover:bg-gray-600">
            Cancel
          </button>
        </div>
      </div>
    </div>
  </div>
  <!-- -->
</div>

Additionally, the component's methods and properties are as follows:

use Livewire\Component;

class Products extends Component
{
   public $products;
   public $showModal = false;


   public function mount()
   {
        $this->products = Product::all();
   }

   public function openModal($productId)
   {
        $this->showModal = true;
        $this->products = Product::where('id', $productId)->first();
   }

    public function closeModal()
    {
        $this->showModal = false;
    }
}

In summary, the problem is that the modal window in the Livewire component is not displaying the correct product information when the "Buy" button is clicked.


Solution

  • Take a new property 'selectedProduct' and use that in view

    public $selectedProduct;
    
    public function openModal($productId)
    {
        $this->showModal = true;
        $this->selectedProduct = Product::where('id', $productId)->first();
    }
    

    And change following in the view

    <div class="px-4 py-3 text-lg font-medium text-gray-800 bg-gray-100">{{ $selectedProduct->name }}</div>
    <div class="p-4">
    <p class="text-gray-700">{{ $selectedProduct->description }}</p>
    </div>