DaemonKeen's avatar

Livewire @if statement is evaluated incorrectly

Hey, I have come across an interesting bug in my Livewire component. The variables inside the @if statement @if($editingService && $selectedService?->id === $service->id) with the 'Editing' badge inside a foreach loop seem to be stuck and not refreshing on Livewire updates. When I add a @dump() directly above it, it shows the values correctly (changing with LW updates). The issue is that when a user enters the edit form and then leaves it, the 'Editing' badge is still present (even though $editingService is false).

Yes, the Livewire template has only one wrapping .

The problematic block:

@if(!empty($services))
    <div class="grid gap-4">
        @foreach($services as $service)
        <div wire:key="{{ $service->id }}"
            @class([
                "rounded-xl border",
                ring-2 ring-blue-200 dark:ring-blue-800"=> $editingService && $selectedService?->id === $service->id
            ])>
            <div class="flex items-start justify-between">
                <div class="flex-1">
                    <div class="flex items-center gap-3 mb-2">
                        <h3 class="text-lg font-medium text-gray-900 dark:text-gray-100">{{ $service->name }}</h3>
                        <x-services.status :status="$service->status" />
                        @dump($editingService)
                        @if($editingService && $selectedService?->id === $service->id) // <-- here
                            <span
                                class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-blue-100 text-blue-800 dark:bg-blue-900/20 dark:text-blue-400">
                                <x-heroicon-o-pencil class="size-3 mr-1" />
                                Editing') }}
                            </span>
                        @endif
                    </div>

Livewire template (at least the most of it):

PHP file:

0 likes
4 replies
DaemonKeen's avatar

Looks like this is not about the loop, but the $editingService variable itself. When I put a @if outside the @foreach it still doesn't work.

<div>
    @dump($editingService) // works normally, returns the variable
    
    @if($editingService) // after first update always true
        <div>this is editing</div>
    @endif

    @foreach($services as $service)
        <div wire:key="service-{{ $service->id }}">
            <div>
                <div>
                    <div>
                        <h3>{{ $service->name }}</h3>
                        <x-services.status :status="$service->status" />
                        @if($editingService && $selectedService?->id === $service->id) // the same
                            <span>
                                <x-heroicon-o-pencil class="size-3 mr-1" />
                                {{ __('Editing') }}
                            </span>
                        @endif
                    </div>
DaemonKeen's avatar
DaemonKeen
OP
Best Answer
Level 1

Okay I figured it out! The problem was in <div wire:transition.duration.300ms>. To be honest I don't know why actually. I think it's because some kind of "Livewire rending process mechanisms".

Options I see here are:

  • to have it without the animation at all
  • use AlpineJS and entangle method.

The broken part:

<!-- Inline Edit Form -->
@if($editingService && $selectedService && $selectedService->id === $service->id)
<div wire:transition.duration.300ms wire:cloak>
    <div class="mt-6 pt-6 border-t border-gray-200 dark:border-gray-700">
        <form wire:submit="saveService" class="space-y-5">
            <div>

Please or to participate in this conversation.