livewire / livewire

A full-stack framework for Laravel that takes the pain out of building dynamic UIs.
MIT License
22.4k stars 1.56k forks source link

Vue component disappears on search or on pagination or filtering #1269

Closed nezaboravi closed 4 years ago

nezaboravi commented 4 years ago

Description

Vue component in foreach loop disappears on search or pagination

Steps to reproduce

I have a table, with rendering rows in foreach loop:

<td class="px-6 py-4 whitespace-no-wrap text-right border-b border-gray-200 text-sm leading-5 font-medium" wire:ignore>
                    <div class="flex items-center justify-center self-center" wire:ignore>
                        <span wire:ignore><approve-button :id="{{ $product->id}}" wire:ignore /></span>
                    </div>
</td>

i tried to add wire:ignore everywhere. One place, parent, parent, all of places, and nothing helped.

Here is image: Initial loading. Shows some products with approval button as expected. Intially selected 'APPROVED' products

Screenshot 2020-07-14 15 39 23

Changing filter to another type and button is gone:

Screenshot 2020-07-14 15 40 12

Back to first filter and button is not there:

Screenshot 2020-07-14 15 40 45

Tried wire:ignore and wire:ignore.self on very component approve-button wire:ignore.self and on all of the parents up to td, nothing worked.

Context All the latest of Laravel, Livewire and tested in Chrome.

Adding some code here: product-list.blade.hp

<tr wire:key="{{ $product->id }}" >
    <td class="px-6 py-4 whitespace-no-wrap border-b border-gray-200">
        <div class="flex items-center">
            <div class="ml-4">
                <div class="text-sm leading-5 font-medium text-gray-900">#A4ALL{{ $product->id }}AD</div>
            </div>
        </div>
    </td>
    <td class="px-6 py-4 whitespace-no-wrap border-b border-gray-200">
        <div class="flex items-center">
            <div class="ml-4">
                <div class="text-sm leading-5 font-medium text-gray-900">{{ $product->country }}</div>
            </div>
        </div>
    </td>
    <td class="px-6 py-4 whitespace-no-wrap border-b border-gray-200">
        <div class="flex items-center">
            <div class="ml-4">
                <div class="text-sm leading-5 font-medium text-gray-900">{{ Str::limit($product->title, 30, ' (...)') }}</div>
                <div class="text-sm leading-5 text-gray-500">{{ $product->cardPhoto }}</div>
            </div>
        </div>
    </td>
    <td class="px-6 py-4 whitespace-no-wrap border-b border-gray-200">
        <span
            class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800">
            {{ !empty($product->created_at) ?$product->created_at->format('y-m-d') : '2000-01-01' }}
        </span>
    </td>
    <td class="px-6 py-4 whitespace-no-wrap border-b border-gray-200">
        <span
            class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800">
            {{ $product->views }}
        </span>
    </td>
    <td
        class="px-6 py-4 whitespace-no-wrap text-right border-b border-gray-200 text-sm leading-5 font-medium">
        <div class="flex items-center justify-center self-center" >
            <span wire:ignore>
                <approve-button :id="{{ $product->id }}"></approve-button>
            </span>
            <span wire:ignore>
                <edit-ad-button :id="{{ $product->id }}"></edit-ad-button>
            </span>
            <span wire:ignore>
                <remove-ad-button :id="{{ $product->id }}"></remove-ad-button>
            </span>
        </div>
    </td>
</tr>

products.blade.php

<tbody class="bg-white">
                @foreach($products as $product)
                    @include('livewire.manager.partials.product-list', ['product' => $product])
                @endforeach
 </tbody>

Products.php


namespace App\Http\Livewire\Manager;

use App\Ad;
use App\Http\Resources\AdResource;
use Livewire\Component;
use Livewire\WithPagination;

class Products extends Component
{
    use WithPagination;

    public $search = '';
    public $perPage = 10;
    public $status = 2;
    /**
     * @var mixed
     */
    public $sortField = 'id';
    public $sortAsc = false;

    /**
     *  Livewire Lifecycle Hook
     */
    public function updatingSearch(): void
    {
        $this->gotoPage(1);
    }

    /**
     *  Livewire Lifecycle Hook
     */
    public function updatingPerPage(): void
    {
        $this->gotoPage(1);
    }

    /**
     *  Livewire Lifecycle Hook
     */
    public function updatingStatus(): void
    {
        $this->gotoPage(1);
    }
    public function clear()
    {
        $this->search = '';
    }

    public function sortBy($field)
    {
        if ($this->sortField === $field) {
            $this->sortAsc = !$this->sortAsc;
        } else {
            $this->sortAsc = true;
        }
        $this->sortField = $field;
    }

    public function render()
    {
        $ads      = Ad::when($this->search, function ($query) {
            $words = explode(' ', $this->search);
            foreach ($words as $word) {
                $query->whereLike(['title', 'description', 'id'], $word);
            }
            return $query;
        })->when($this->status, function($query){
            return $query->where('status', $this->status);
        })

                      ->orderBy($this->sortField, $this->sortAsc ? 'ASC' : 'DESC')
                      ->with('user')->with('media')->with('category')
                      ->paginate($this->perPage);
        $products = AdResource::collection($ads);

        return view('livewire.manager.products', ['products' => $products]);
    }
}
nezaboravi commented 4 years ago

Here is what i see in dev tools after sorting, or filtering.

Screenshot 2020-07-14 20 51 50

@calebporzio help please?

nezaboravi commented 4 years ago

Got this button works importing livewire-vue , but on every change now (filter, pagination, search, clear search), buttons, my vue components, not reacting, it works only when first time load page, then every component reacts. click go to next page, or filter by 20 records, or search by keywords, it not work anymore.

nuernbergerA commented 4 years ago

Hey @nezaboravi,

make sure to use wire:key https://laravel-livewire.com/docs/troubleshooting

Cheers

nezaboravi commented 4 years ago

@nuernbergerA thanks for the tip. I am using it. I use wire:key . updated description with a code. I have tried to use it on table row where the vue component are, i tried to use it on parent span/div on vue component, and even on component it self, and nothing helped

calebporzio commented 4 years ago

Closing this.

Vue support is isolated to the following repo: https://github.com/livewire/vue

Please re-submit any issues there.

Thanks!