How to Refresh Widgets When Table Actions Are Fired

Mar 4, 2023
Leandro C. Ferreira
Admin panel, Laravel, Livewire, Table builder



In this article, we will explore how to use Filament widgets to create statistic cards that display user statistics about the user table. We will also see how to refresh the widgets when the user table is changed, using Livewire lifecycle hooks and events.


To get started with the Filament, you can install a new Laravel project called filament-widget-examples:

laravel new filament-widget-examples

Now you can install Filament using the command:

cd filament-widget-examples
composer require filament/filament

Filament recommends adding this to your composer.json's post-update-cmd:

"post-update-cmd": [
// ...
"@php artisan filament:upgrade"

Edit the User Migration File:

Schema::create('users', function (Blueprint $table) {

Edit the User Factory definition method:

public function definition()
return [
'name' => fake()->name(),
'email' => fake()->unique()->safeEmail(),
'email_verified_at' => now(),
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
'remember_token' => Str::random(10),
'is_admin' => fake()->boolean(),
'is_active' => fake()->boolean(),

Edit the DatabaseSeeder run method:

public function run()

Edit the User Model:

protected $fillable = [

Run the migrate command:

php artisan migrate --seed

User Resource

You can create a User Resource and a Widget:

php artisan make:filament-resource User --simple
php artisan make:filament-widget UserOverview --resource=UserResource --stats-overview

Edit the User Resource file:


public static function form(Form $form): Form
return $form


public static function table(Table $table): Table
return $table

Including widgets

Add the getWidgets method:

use App\Filament\Resources\UserResource\Widgets\UserOverview;
public static function getWidgets(): array
return [

Add the getHeaderWidgets method:

protected function getHeaderWidgets(): array
return [

Widget cards

You can use the Widget cards to display a number of different stats in a single widget. Edit the Users Overview Widget to this:

class UserOverview extends BaseWidget
protected static ?string $pollingInterval = null;
protected function getCards(): array
$usersCount = User::selectRaw('
COUNT(*) as total,
SUM(CASE WHEN is_admin THEN 1 ELSE 0 END) AS admin,
SUM(CASE WHEN is_active THEN 1 ELSE 0 END) AS active
return [
Card::make('Total', $usersCount->total)
->description('Total users'),
Card::make('Admin', $usersCount->admin)
->description('Admin users'),
Card::make('Active', $usersCount->active)
->description('Active users'),

Check the User Resource on your browser. We have three header widgets: Total users, Admin users and Active users.


You can delete users in the table, but these widgets won't be updated, only the table. You need to refresh the page to update the widgets.

Refresh widgets automatically

Livewire lifecycle

Each Livewire component undergoes a lifecycle. Lifecycle hooks allow you to run code at any part of the component's lifecyle. We can use the Updated hook to runs after any update to the Livewire component's data.

Livewire event listeners

Listeners are a key->value pair where the key is the event to listen for, and the value is the method to call on the component.

We can use the $refresh magic action to re-render the component without firing any action.

Let's add a listener in the Users Overview Widget file:

protected $listeners = ['updateUserOverview' => '$refresh'];

The updated hook method provides two attributes:

  • $name: the name of the action that was fired.
  • $value: the value of the action that was fired.

We are going to use the $name attribute to listen to two table events:

  • mountedTableAction: executed after a single delete action is clicked.
  • mountedTableBulkAction: executed after a bulk delete action is clicked.

Then, we can check these names in the updated method and emit the updateUserOverview event:

public function updated($name)
if (Str::of($name)->contains(['mountedTableAction', 'mountedTableBulkAction'])) {

Now, the widgets will always be updated when the delete action is clicked.


You can also check other table events, for example:

//text input in the top right of the table
if (Str::of($name)->contains('tableSearchQuery')) {
//the table filter form
if (Str::of($name)->contains('tableFilters')) {

This project is available on Github:

I hope you enjoy it :)

No comments yet…