I have a table products
and job_statuses
using this package: laravel-job-status
There is a column in job_statuses
called status
the package made this column finished
once the queue job is finished!
So I created a column in products
table called job_status_id
(relation with job_statuses) just to save the job status id in the products table to see if this job is finished!
Simply I created a component using Livewire
for just refresh single product when the job finished refresh the component:
class ProductIndex extends Component
{
public $product;
public function mount($product)
{
$this->product = $product;
}
public function render()
{
return view('livewire.merchant.product.index');
}
}
Inside product-index
component:
@if ($product->job_status->status == 'finished')
// show real image
@else
// show loader
@endif
My blade:
@foreach ($products as $product)
<livewire:merchant.product.product-index :product="$product" :key="$product->id">
@endforeach
How can refresh the product component if the status is finished?
You can add an event-listener in your component, then fire an event from anywhere on the page - even from JavaScript - to refresh the component.
To add a listener to make the component refresh itself, simply add the following line to your
ProductIndex
component.Livewire will now listen for any
refreshProducts
events that are emitted, and once they are emitted, it will refresh that component.You can also customize it further, by replacing the magic
$refresh
action with a method, which you can pass parameters to. If you name the event the same as the method, you don't need to specify a key/value pair (eventname as the key, methodname as the value), and the value alone will suffice. Here's an example,From within a Livewire component, you can emit events using
You can also emit events from JavaScript, by doing
If you want to make the queue trigger that event once its complete, you need to implement something that either polls the server to ask "has the job finished" and then fire the event, or you can use Laravel Echo as a websocket. This will allow you to fire and listen for events from outside the Livewire ecosystem.
Polling
Polling is the easiest way to continuously update a Livewire component, it does not require any websockets integration like Laravel Echo. This means that every X seconds (default is 2 seconds), your component is going to make an AJAX request to your server, to fetch its newest data, and re-render itself with the new data.
This is easily achieved by wrapping the component with the
wire:poll
attribute - here's an example of using 5 seconds.However, this means that all instances of that component will re-render themselves and fire an AJAX request of their own to the server to get the newest data. You might want to make a "parent" component for all your items, thereby just having 1 singular component re-render.
Broadcasting & Websockets
I'm going to assume that you have installed Laravel Echo already. Now - to achieve this functionality of broadcasting, you first need to create an event. Run the command
This will create an event in your
app\Events
folder. Customize it to however you need it. It will look something like this after running the command,We can change the channel from
PrivateChannel('channel-name')
toChannel('products')
, this allows us to listen for it in Livewire in the products channel (you could name the channel whatever you want, and you can also listen for private events - there's documentation for that in the Livewire documentation, referenced at the bottom of this answer).So that means the
broadcastOn
would look something like thisNext, after the job has completed its work and all the statuses has been set, fire that event from Laravel, using
Now we need to update our listener in the Livewire component, so that we can actually listen for the broadcast on that channel through Laravel Echo (and not the Livewire events that we did before).
And we're done! You're now using Laravel Echo to broadcast an event, which Livewire intercepts, and then runs. The listener is now a key/value pair, where the value is still the method name in the component (you can still use the magic action
$refresh
instead if you desire to), and the key ischannel,event
prefixed byecho:
.Resources: