luisfer
luisfer

Reputation: 2120

Laravel Livewire/AlpineJS: Disable a button while loading data from an API and then enabling it again

This should be really simple, but I don't get it. I want to replicate the functionality of a button that when pressed goes to an API (which could take about a minute to get the data and process it), it gets diabled, and after loading the data it gets enabled.

I'm using Laravel/Livewire/Alpine

So, in my livewire component I have:

public $loading = false;

In my blade file, I have the declaration for the div where the button is:

  <div
    class="grid grid-cols-3 gap-4"
    x-data="{
      loading: @entangle('loading')
    }"
    >

Then the button x-binds the disabled property to the loading value, when the button is clicked, it changes the property of the loading variable, and calls the loader function

    <button
      type="button"
      class="btn btn-sm btn-jbn"
      x-on:click="loading = true"
      x-bind:disabled="loading"
      wire:click="loader"
      >
      Load API
    </button>

And it does what it is supposed to do... the button is grayed, it becomes unusable, the cursor change, etc., it executes the loader function in my livewire component, but it never return to the normal state after loading the API. In my livewiere componente I have:

public function loader() {
  // API call and logic goes here, this works

  $this->loading = false;
}

So I would imagine that at the end of the API process the entangled variable loading would return the button to its normal state, but it doesn't

What am I missing?

Upvotes: 4

Views: 8796

Answers (1)

Qirel
Qirel

Reputation: 26450

Livewire already has incorporated functionality to handle loading-states. Instead of implementing your own, you can use this.

Get rid of all your current loading-logic, and simply use wire:loading with wire:target on your button.

wire:loading can toggle the disabled attribute directly by doing wire:loading.attr="disabled", and wire:target is to set the target for that loading-state to the method you are calling, so in your case that's wire:target="loader".

This means your button looks like this,

<button
    type="button"
    class="btn btn-sm btn-jbn"
    wire:click="loader"
    wire:loading.attr="disabled" 
    wire:target="loader"
>
    Load API
</button>

Upvotes: 5

Related Questions