Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

valentin_vranic's avatar

wire:loading spinner, bootstrap 5

Hi folks. I would like to have your notes and ideas about, how to add effectively and dynamically spinner on button on form submit globally?

I know about this kind of solution:

<form wire:submit="save">
    <!-- ... -->
 
    <button type="submit">Save</button>
 
    <div wire:loading> 
        Saving post...
    </div>
</form>

but with this approach I'm gonna always have to add separately.

Thanks in advance, Vale

0 likes
3 replies
valentin_vranic's avatar

@martinbean Thanks for advice. I've did it that way. Now what I'm facing is, that even if I set the target the all the button which are "created" by this extracted component disappear and only the one clicked has the spinner. I want to achieve only to spin the clicked button.

@props([
    'type' => 'button',
    'target' => ''
])

<button
    wire:loading.remove
    {{ $attributes->merge(['class' => 'btn']) }}
    {{ $attributes->merge(['type' => $type]) }}
    {{ $attributes["event"] ?? ''}}
>
    {{ $slot }}
</button>

<div wire:loading wire:target="{{ $target ?? '' }}"
    class="spinner-border text-primary" role="status">
    <span class="sr-only">Loading...</span>
</div>
<x-assets.button class="btn-primary" type="submit" target="filter">
    {{ __('messages.Filter') }}
</x-assets.button>
<x-assets.button class="btn-sm btn-primary pt-0 pb-0"
    event="wire:click=getRejectDetails('all')"
    target="getRejectDetails">
    {{ __('messages.Details') }}
</x-assets.button>
LaryAI's avatar
Level 58

To implement a global spinner for form submissions using Livewire and Bootstrap 5, you can create a reusable Livewire component that includes the spinner. This way, you can simply include this component in any form without having to repeatedly write the spinner code.

Here's how you can create a reusable Livewire component for a button with a loading spinner:

  1. Create a Livewire Component: First, create a new Livewire component. Let's call it loading-button.

    php artisan make:livewire LoadingButton
    
  2. Modify the Component View: Edit the view of the loading-button component to include the button and the spinner. Here, we'll use Bootstrap 5 classes for the spinner.

    <!-- resources/views/livewire/loading-button.blade.php -->
    <div>
        <button type="submit" class="btn btn-primary" wire:loading.attr="disabled">
            <span wire:loading.remove>{{ $slot }}</span>
            <span wire:loading class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
            <span wire:loading>Loading...</span>
        </button>
    </div>
    

    In this template:

    • wire:loading.remove hides the slot content (button label) when loading.
    • wire:loading shows the spinner and the "Loading..." text only during the loading state.
    • wire:loading.attr="disabled" disables the button while loading to prevent multiple submissions.
  3. Use the Component in Forms: You can now use this component in any form by wrapping the button label with the <livewire:loading-button> tag.

    <form wire:submit.prevent="save">
        <!-- Form fields here -->
        <livewire:loading-button>
            Save
        </livewire:loading-button>
    </form>
    

This approach encapsulates the loading logic within a single Livewire component, making it easy to reuse across different forms in your application. It also keeps your code DRY (Don't Repeat Yourself) and clean, as you avoid duplicating the spinner code in every form.

Please or to participate in this conversation.