Search code examples
jquerylaravelloopslaravel-bladelaravel-livewire

Is it possible to use .one on jQuery per class name even if it changes per input search in Livewire?


I have here a grid layout that shows products and on each product click, it displays the product details on a table using Datatables. Right now, I'm trying to only fire the click event once per product by using jQuery's one and it's working fine. However, when I search an item, it works fine for the first click, but then on the next search then click, it won't. How can I make it work per one click of each product even when searched? Not sure if this is just on livewire, or on JS.

I've used livewire, laravel blade and js on this one.

Here's my JS:

$('.box-product').one('click', function(e) {
    e.preventDefault();
    let $productId = $(this).attr('data-id');
    loadDataTable($productId);
    playBeepSound();
});

And part of my Laravel blade:

 <div class="grid md:grid-cols-1 lg:grid-cols-2 gap-4 grid-container" >
        @foreach($products as $product)
            <div class="mb-3 bg-white shadow-md hover:shadow-xl active:border-2 active:border-indigo-500 rounded-lg cursor-pointer transition ease-in-out duration-150 box-product" data-id="{{ $product->id }}">
                <div class="py-4 px-4">
                    <div class="flex flex-col">
                        <div class="bg-persian-blue p-2 mb-3 flex flex-wrap items-center justify-center text-gray-50 rounded-full font-mono w-24 h-24">₱ @money($product->cost)
                        </div>                        
                        <h4 class="text-lg font-semibold mb-3">{{ $product->name }}</h4>
                        <p class="text-sm text-gray-500">{{ $product->description }}</p>
                    </div>
                </div>
            </div>
        @endforeach
    </div>

my controller:

<?php

namespace App\Http\Livewire;

use Livewire\Component;
use App\Models\Product;

class LoadMoreProducts extends Component
{
    public $searchTerm;
    public $amount = 10;

    protected $listeners = [
        'load-more' => 'loadMore'
    ];
   
    public function loadMore()
    {
        $this->amount = $this->amount + 10;
    }

    public function render()
    {
        $searchTerm = '%' . $this->searchTerm . '%';
        $products = Product::orderBy('name')->where('code', 'like', $searchTerm)
                        ->orWhere('name', 'like', $searchTerm)
                        ->orWhere('description', 'like', $searchTerm)
                    ->paginate($this->amount);
        $this->emit('productStore');

        return view('livewire.load-more-products', ['products' => $products]);
    }
}

Any help is much appreciated.


Solution

  • I've managed to solve this by moving my jquery code to the livewire blade code, and adding it inside document.addEventListener('livewire:load', function (){});. See code below:

    <div>
        <div class="mb-6">
            <div class="pt-2 relative mx-auto text-gray-600">
                <input class="py-3 px-4 focus:border-indigo-500 block w-full pr-12 border-gray-200 rounded border-2" name="load-more-search" id="load-more-search" type="search" tabindex="1" placeholder="Search a product or scan barcode" wire:model="searchTerm" autofocus />
                <svg class="absolute right-0 top-0 mt-6 mr-6 text-gray-600 h-4 w-4 fill-current" xmlns="http://www.w3.org/2000/svg"
                    xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Capa_1" x="0px" y="0px"
                    viewBox="0 0 56.966 56.966" style="enable-background:new 0 0 56.966 56.966;" xml:space="preserve"
                    width="512px" height="512px">
                    <path
                        d="M55.146,51.887L41.588,37.786c3.486-4.144,5.396-9.358,5.396-14.786c0-12.682-10.318-23-23-23s-23,10.318-23,23  s10.318,23,23,23c4.761,0,9.298-1.436,13.177-4.162l13.661,14.208c0.571,0.593,1.339,0.92,2.162,0.92  c0.779,0,1.518-0.297,2.079-0.837C56.255,54.982,56.293,53.08,55.146,51.887z M23.984,6c9.374,0,17,7.626,17,17s-7.626,17-17,17  s-17-7.626-17-17S14.61,6,23.984,6z" />
                </svg>
            </div>
        </div>
        <div class="grid lg:grid-cols-1 xl:grid-cols-2 gap-4 grid-container" >
            @foreach($products as $product)
                <div class="mb-3 bg-white shadow-md hover:shadow-xl active:border-2 active:border-indigo-500 rounded-lg cursor-pointer transition ease-in-out duration-150 box-product" data-id="{{ $product->id }}">
                    <div class="py-4 px-4">
                        <div class="flex flex-col">
                            <div class="bg-persian-blue p-2 mb-3 flex flex-wrap items-center justify-center text-gray-50 rounded-full font-mono w-24 h-24">₱ @money($product->cost)
                            </div>                        
                            <h4 class="text-lg font-semibold mb-3">{{ $product->name }}</h4>
                            <p class="text-sm text-gray-500">{{ $product->description }}</p>
                        </div>
                    </div>
                </div>
            @endforeach
        </div>
    </div>
    <script>
        document.addEventListener('livewire:load', function () {
            $('.box-product').one('click', function(e) {
                let $productId = $(this).attr('data-id');
                loadDataTable($productId);
                playBeepSound(); 
            });
        });
    </script>