php - Laravel Livewire Component not updating - Stack Overflow

admin2025-04-27  3

I'm struggling with a simple livewire component. It's a button that adds or removes ids from an array (and also to the session). After adding a modal should appear with the different attributes.

The other components are not updating when the toggle method is called, same for the modal.

Loop:

@foreach ($listings as $listing)
    <h1>{{$listing->title}}</h1>
    <livewire:compare-listings :listing="$listing"/>
@endforeach

CompareListings.php

namespace App\Livewire;

use App\Models\Listing;
use Livewire\Attributes\Session;
use Livewire\Component;

class CompareListings extends Component {

    public Listing $listing;

    #[Session]
    public array $comparisonList = []; // List of IDs

    public function toggleComparison($id): void {

        if (!in_array($id, $this->comparisonList)) {
            // Add ID
            $this->comparisonList[] = $id;
        } elseif (($key = array_search($id, $this->comparisonList)) !== false) {
            // Remove ID
            unset($this->comparisonList[$key]);
            // Sort array
            $this->comparisonList = array_values($this->comparisonList);
        }

    }
    public function render() {
        return view('livewirepare-listings', [
            'listings' => Listing::whereIn('id', $this->comparisonList)->get()
        ]);
    }
    
}

compare-listings.blade.php

<div>

    <button data-modal-target="compareModal" data-modal-toggle="compareModal"
            class="mt-4 bg-gray-700 text-white px-4 py-2 rounded">
        {{ __('Show comparison list') }}
    </button>

    <button wire:click="toggleComparison({{ $listing->id }})">
        {{ __('Add/Remove comparison list') }}
    </button>

    @php
        var_dump($comparisonList);
    @endphp

    {{--    <!-- Modal -->--}}
    @push('modals')
        <div id="compareModal" tabindex="-1">
            Comparison Table
        </div>
    @endpush

I'm struggling with a simple livewire component. It's a button that adds or removes ids from an array (and also to the session). After adding a modal should appear with the different attributes.

The other components are not updating when the toggle method is called, same for the modal.

Loop:

@foreach ($listings as $listing)
    <h1>{{$listing->title}}</h1>
    <livewire:compare-listings :listing="$listing"/>
@endforeach

CompareListings.php

namespace App\Livewire;

use App\Models\Listing;
use Livewire\Attributes\Session;
use Livewire\Component;

class CompareListings extends Component {

    public Listing $listing;

    #[Session]
    public array $comparisonList = []; // List of IDs

    public function toggleComparison($id): void {

        if (!in_array($id, $this->comparisonList)) {
            // Add ID
            $this->comparisonList[] = $id;
        } elseif (($key = array_search($id, $this->comparisonList)) !== false) {
            // Remove ID
            unset($this->comparisonList[$key]);
            // Sort array
            $this->comparisonList = array_values($this->comparisonList);
        }

    }
    public function render() {
        return view('livewire.compare-listings', [
            'listings' => Listing::whereIn('id', $this->comparisonList)->get()
        ]);
    }
    
}

compare-listings.blade.php

<div>

    <button data-modal-target="compareModal" data-modal-toggle="compareModal"
            class="mt-4 bg-gray-700 text-white px-4 py-2 rounded">
        {{ __('Show comparison list') }}
    </button>

    <button wire:click="toggleComparison({{ $listing->id }})">
        {{ __('Add/Remove comparison list') }}
    </button>

    @php
        var_dump($comparisonList);
    @endphp

    {{--    <!-- Modal -->--}}
    @push('modals')
        <div id="compareModal" tabindex="-1">
            Comparison Table
        </div>
    @endpush
Share Improve this question asked Jan 11 at 13:11 BloxxorBloxxor 356 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 1

The question is not entirely clear, however from what I see, you are not assigning a unique key to the component included in the loop. This can cause incorrect synchronization between the rendered view and the view already displayed

@foreach ($listings as $listing)

    ....

    <livewire:compare-listings :listing="$listing" :key="$listing->id" />

@endforeach

In this way the compare-listings view receives a unique key (the record id) and is updated correctly. Here you can find the related documentation.

An additional tip
You can avoid traversing the $comparisonList array twice when deleting an element (the first time with in_array, the second time with array_search) by simply refactoring the toggleComparison() method like this:

function toggleComparison($id) 
{
    if (($index = array_search($id, $this->comparisonList)) !== false) {
        array_splice($this->comparisonList, $index, 1);
    }
    else {
        $this->comparisonList[] = $id;
    }
}

I had to place a dispatch event that calls a method to update the component. It`s not very performant so I think about refactoring it via JavaScript.

Solution:

At the end of the method toggleComparison()

$this->dispatch('listUpdated', $this->comparisonList);

Add a new method

#[On('listUpdated')]
public function refreshListStatus(): void {
    $this->comparisonList = session()->get('compareListings', []);
}

This solves the problem.

转载请注明原文地址:http://anycun.com/QandA/1745710238a91145.html