Issue with simultaneous loading states display in Livewire button Problem Description
I'm experiencing an issue with loading states display in a Livewire form button. The button is showing both states ("Send" and "Sending...") simultaneously instead of toggling between them correctly.
Current Code
<button type="submit" wire:loading.attr="disabled" class="w-full px-4 py-2 rounded-lg bg-indigo-700 text-white hover:bg-indigo-800 transition duration-150 ease-in-out disabled:opacity-50 disabled:cursor-not-allowed">
<div class="flex items-center justify-center">
<span wire:loading.remove wire:target="submit">
Send
</span>
<span wire:loading wire:target="submit" class="flex items-center">
<svg class="animate-spin -ml-1 mr-3 h-5 w-5 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
Sending...
</span>
</div>
</button>
How can I fix this simultaneous states display issue in the button? Is there a better way to handle loading states in Livewire?
Thank you in advance for your help!
Where is the submit action (not button type) that you are targetting? IMHO, you don't need the wire:target directive in this case; but maybe if there is a bigger context that we are not seeing???
@tykus
thanks for your reply.
this is the action on the livewire class :
public function submit()
{
$this->validate();
try {
Mail::raw("Nouveau message de contact:\n\nNom: {$this->name}\nEmail: {$this->email}\nTéléphone: {$this->phone}\n\nMessage:\n{$this->message}", function($message) {
$message->to('')
->subject('Nouveau message de contact');
});
$this->reset(['name', 'email', 'phone', 'message']);
$this->dispatch('messageSent');
} catch (\Exception $e) {
$this->dispatch('messageError');
}
}
this is the complete form :
<form wire:submit="submit" class="space-y-4 px-2 sm:px-6">
@if (session()->has('message'))
<div class="bg-green-100 border border-green-400 text-green-700 px-3 py-2 sm:px-4 sm:py-3 rounded relative">
{{ session('message') }}
</div>
@endif
@if (session()->has('error'))
<div class="bg-red-100 border border-red-400 text-red-700 px-3 py-2 sm:px-4 sm:py-3 rounded relative">
{{ session('error') }}
</div>
@endif
<div class="space-y-2">
<label class="block text-gray-800">Nom</label>
<input type="text" wire:model="name" placeholder="Entrez votre nom"
class="w-full px-3 py-2 sm:px-4 sm:py-2 border border-gray-400 rounded-sm focus:ring-2 focus:ring-indigo-500 focus:border-transparent">
@error('name')
<p class="text-red-500 text-sm">{{ $message }}</p>
@enderror
</div>
<div class="space-y-2">
<label class="block text-gray-800">Email</label>
<input type="email" wire:model="email" placeholder="Entrez votre adresse email"
class="w-full px-3 py-2 sm:px-4 sm:py-2 border border-gray-400 rounded-sm focus:ring-2 focus:ring-indigo-500 focus:border-transparent">
@error('email')
<p class="text-red-500 text-sm">{{ $message }}</p>
@enderror
</div>
<div class="space-y-2">
<label class="block text-gray-800">Numéro de téléphone</label>
<input type="tel" wire:model="phone" placeholder="Entrez votre numéro de téléphone"
class="w-full px-3 py-2 sm:px-4 sm:py-2 border border-gray-400 rounded-sm focus:ring-2 focus:ring-indigo-500 focus:border-transparent">
@error('phone')
<p class="text-red-500 text-sm">{{ $message }}</p>
@enderror
</div>
<div class="space-y-2">
<label class="block text-gray-800">Message</label>
<textarea wire:model="message" placeholder="Entrez votre message" rows="4"
class="w-full px-3 py-2 sm:px-4 sm:py-2 border border-gray-400 rounded-sm focus:ring-2 focus:ring-indigo-500 focus:border-transparent"></textarea>
@error('message')
<p class="text-red-500 text-sm">{{ $message }}</p>
@enderror
</div>
<div class="mt-6 grid grid-cols-1 md:grid-cols-2 gap-3 sm:gap-4">
<a href="{{ route('home') }}"
class="text-center w-full px-3 py-2 sm:px-4 sm:py-2 rounded-lg border border-gray-300 hover:bg-gray-50">
Annuler
</a>
<button type="button"
wire:click="submit"
wire:loading.attr="disabled"
class="w-full px-3 py-2 sm:px-4 sm:py-2 rounded-lg bg-indigo-700 text-white hover:bg-indigo-800 transition duration-150 ease-in-out disabled:opacity-50 disabled:cursor-not-allowed">
<div class="flex items-center justify-center">
<span wire:loading.remove >
Envoyer
</span>
<span wire:loading class="flex items-center">
<svg class="animate-spin -ml-1 mr-3 h-5 w-5 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
Envoi en cours...
</span>
</div>
</button>
</div>
</form>
@rutem because you are using wire:submit="submit" you can do the following with your button
<button
+ type="submit"
- type="button"
- wire:click="submit"
wire:loading.attr="disabled"
...rest of code
</button>
I would suggest changing your method name from submit to something else as well
@rutem if are using wire:submit on the form, then why have you changed the button to a button type, and added wire:click???
Please sign in or create an account to participate in this conversation.