Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Search two time then change paginate table record have problem #1908

Closed
sueboy19 opened this issue Oct 27, 2020 · 9 comments
Closed

Search two time then change paginate table record have problem #1908

sueboy19 opened this issue Oct 27, 2020 · 9 comments

Comments

@sueboy19
Copy link

sueboy19 commented Oct 27, 2020

Description

Step

  1. Start empty Search get 12 record. Paginate is 10 record/page have two page.
  2. Search "c" get 1 record. (id = 5)
  3. Delete Search "c". Get same step 1. get 16 record. Paginate is 10 record/page have two page.
  4. Click page 2. See two records. second records get id is 5. Correct is get id = 12.

Exact steps to reproduce

Stripped-down, copy-pastable code snippets

search_pagin

orders.blade.php

<table>
  <thead>
    <tr>
      <th>
         record
      </th>
    </tr>
  </thead>
  <tbody>
  @foreach($orders as $key => $order)
    <tr>
      <td>
          A. {{ $order->id }}
          B. <button data-toggle="modal"  class="btn btn-info" 
               wire:click="show({{ $order->id }})" 
               wire:key="show{{ $loop->index }}">{{ trans('global.show') }}  </button>
      </td>
      <td>
          C. @livewire('order.delete', ['id' => $order->id], key('delete'.$loop->index))
      </td>
    </tr>
  @endforeach
  </tbody>
</table>
{{ $orders->links('livewire.common.pagination-links-view') }}

Orders.php

use Livewire\Component;
use Livewire\WithPagination;

class Orders extends Component
{
    use WithPagination;
    public $search = '';
    protected $paginationTheme = 'bootstrap';

public function updatingSearch()
    {
        $this->resetPage();
    }

public function render()
  {
    $searchText = '%'.$this->search.'%';
    $orders = Order::where('name', 'like', $searchText)->paginate(10);
    return view('livewire.order.orders', [
            'orders' => $orders, 
    ]);
}

public function show($id)
{
   return redirect()->to('/admin/order/show/'.$id);
}

public function delete($id){
  return redirect()->to('/admin/order/delete/'.$id);
}

delete.blade.php

<button class="btn btn-danger" onclick="confirm('{{ trans('global.areYouSure') }}') || event.stopImmediatePropagation()"  style="display: inline-block;"
    wire:click="delete()"> 
    {{ trans('global.delete') }}
</button>

Delete.php

use Livewire\Component;

class Delete extends Component
{
    public $order_id;

    public function mount($id)
    {
        info($id);
        $this->order_id = $id;
    }

    public function render()
    {
        abort_if(Gate::denies('order_delete'), Response::HTTP_FORBIDDEN, '403 Forbidden');

        return view('livewire.order.delete');
    }

    public function delete()
    {
        dd($this->order_id);
        $order = Order::findOrFail($this->order_id);
        $order->delete();
        // $order->clearMediaCollection(); // 無效
        
        session()->flash('message', 'Order Deleted Successfully.');
        $this->back();
    }

    public function back()
    {
        $this->previousUrl = session('url.intended');
        return redirect($this->previousUrl);
        // return redirect('/admin/order');
    }
}

A. B. always get Correct id. But C. can't. When follow Step, C always $order->id get 5.
If change key:
Use $order->id or 'delete'.$order->id get other problem.
Only use $loop->index still get problem.

['id' => $order->id] change ['order' => $order] get same problem. Always $order->id get 5.

If use Div try to include show or delete action, still not use.

I think Nesting Components use "@livewire" have some bug inside for Search.

Context

  • PHP version: 7.4.11
  • Livewire version: 2.3.0
  • Laravel version: 8.11.2
  • Alpine version: -
  • Browser: Chrome 86.0.4240.111
@joshhanley
Copy link
Member

I think using $loop->index as your key could be causing you problems, try using $order->id as the key as it should be unique to each record.

The other thing is try is putting wire:key on the <tr> instead, (and using the id as I suggested)

@foreach($orders as $key => $order)
    <tr wire:key="{{ $order->id }}">

@sueboy19
Copy link
Author

sueboy19 commented Oct 28, 2020

I try at tr

<tr wire:key="{{ $order->id }}">

get more error.

  1. Show index then click page 2, get error is
Uncaught (in promise) TypeError: Cannot read property 'fingerprint' of null

And Page 2 record is only show one record. Other records is old page 1.

  1. Search then Clean Search get error is
Uncaught (in promise) TypeError: Cannot read property 'fingerprint' of null

And All records only last two record and button number is warring.

I try many way. I think wire:key not real key.
Button use wire:key is different @livewire(..., key(...)) have two different mean.

https://laravel-livewire.com/docs/2.x/troubleshooting

wire:key how to use is different we think.

@JeffGepiga
Copy link

got the same issue, any work around for this?

@sueboy19
Copy link
Author

sueboy19 commented Oct 28, 2020

@theonly27 Don't use @livewire Just use button. Now I do this way.

@uteq
Copy link

uteq commented Oct 28, 2020

This indeed looks like Livewire not being able to keep track of the correct elements. I've had similar problems in my projects.
My eventual solution was to use AlpineJs for this. Alpine was able to keep track of the correct items.

@joshhanley
Copy link
Member

joshhanley commented Oct 28, 2020

Ok, so I have just pulled down your code into one of my test projects and got it working, as I suggested, you need to use $order->id for the wire:key on the <tr> but you also need it on the child component @livewire('delete', ['id' => $order->id], key('delete'.$order->id))

The unique ID is important as the DOM diffing won't work correctly as you have found. I tried it without passing the key to the child component and that broke it.

So I would recommend in any situation you need this, to put wire key on the parent most element inside a loop (like the or a div or whatever), but also pass a wire key to each child component you may have in that row.

Hope this helps!

Full code is below

@foreach($orders as $key => $order)
    <tr wire:key="{{ $order->id }}">
    <td>
        A. {{ $order->id }}
        B. <button data-toggle="modal"  class="btn btn-info"
                wire:click="show({{ $order->id }})">Show</button>
    </td>
    <td>
        C. @livewire('delete', ['id' => $order->id], key('delete'.$order->id))
    </td>
    </tr>
@endforeach

@sueboy19
Copy link
Author

sueboy19 commented Oct 29, 2020

@joshhanley Thank you very much. I try then now get all answer. Correct is 5 and 6.

Use tr + wire:key $order->id and inside wire:key use unique key name + $order->id.

@foreach($orders as $key => $order)
    <tr wire:key="{{ $order->id }}">
    <td>
        A. {{ $order->id }}
        B. <button data-toggle="modal"  class="btn btn-info"
                wire:click="show({{ $order->id }})">Show</button>
    </td>
    <td>
        C. @livewire('delete', ['id' => $order->id], key('delete'.$order->id))
    </td>
    </tr>
@endforeach

This is all test result.

  1. show, add, edit, delete, @livewire delete all use $loop->index
    1_all_loop_index

  2. show, add, edit, delete use $loop->index, @livewire delete use $order->id
    2_some_loop

  3. show, add, edit, delete, @livewire delete all use $order->id
    3_all_order_id

Add at TR wire:key="{{ $order->id }}
4.
show, add, edit, delete, @livewire delete all use $loop->index
4_tr_key_all_loop_index

  1. show, add, edit, delete use $loop->index, @livewire delete use $order->id
    5_tr_key_some_loop

show, add, edit, delete, @livewire delete all use $order->id
6_tr_key_all_order_id

  1. show, add, edit, delete, @livewire delete remove unique key name.
    this mean is
    wire:key="delete{{ $order->id }}" -> wire:key="{{ $order->id }}"

     key('delete'.$order->id)) -> key($order->id)
    

7_tr_key_remove_unique_key_name

@joshhanley
Copy link
Member

Posting all the screenshots is confusing.

So did you get it work in the end?

If so can you please close the issue, and maybe put a one line summary (not screenshots) of what worked best incase someone else comes across this issue in the future. :)

@squishythejellyfish
Copy link
Collaborator

👋 Oh Hi! I'm Squishy, the friendly jellyfish that manages Livewire issues.

I see this issue has been closed.

Here in the Livewire repo, we have an "issues can be closed guilt-free and without explanation" policy.

If for ANY reason you think this issue hasn't been resolved, PLEASE feel empowered to re-open it.

Re-opening actually helps us track which issues are a priority.

Reply "REOPEN" to this comment and we'll happily re-open it for you!

(More info on this philosophy here: https://twitter.com/calebporzio/status/1321864801295978497)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants