Skip to main content

Dashboard Widgets: Stats, Charts, Tables and Header/Footer

Premium
9:26

Text Version of the Lesson

Filament has a concept of "Widget", which may be used in different contexts on different pages. But the most typical use case is the Dashboard: you can replace the default "Information" blocks with your own widgets.

This is what the default Dashboard looks like:

Not very useful, is it? A typical user shouldn't even know what version of Filament is running under the hood.

So let's add a few widget blocks here. Filament offers three typical widget types:

  • Stats Overview
  • Chart
  • Table

I will show you all three, in this lesson.


Stats Overview: Total Revenue Widget

We will calculate the total revenue from orders in three slices: the sum of orders.price today, over the last 7 days and 30 days.

For that, we generate a Widget with the type stats-overview:

php artisan make:filament-widget RevenueToday --stats-overview

Important: this Artisan command requires choosing the panel. Since widgets can be used outside of the dashboard as separate Livewire components, you need to choose specifically "admin" if you want to use it on the dashboard.

Then it generates the file in app/Filament/Widgets where we need to fill in the getStats() method. The syntax is this:

app/Filament/Widgets/RevenueToday.php:

use App\Models\Order;
use Filament\Widgets\StatsOverviewWidget\Stat;
 
class RevenueToday extends BaseWidget
{
protected function getStats(): array
{
$totalRevenue = Order::whereDate('created_at', date('Y-m-d'))->sum('price') / 100;
 
return [
Stat::make('Revenue Today (USD)',
number_format($totalRevenue, 2))
];
}
}

As you can see, we have two parameters to Stat::make(): the title and the number/text we want to show.

And that's it. We have a new widget on the dashboard. No need to configure anything else!

But of course, this is just the beginning of our dashboard. Let's generate...

The Full Lesson is Only for Premium Members

Want to access all of our courses? (30 h 09 min)

You also get:

55 courses
Premium tutorials
Access to repositories
Private Discord
Get Premium for $129/year or $29/month

Already a member? Login here

Comments & Discussion

R
RicLeP ✓ Link copied!

How do you add a link to a table widget to view the item?

Found it in your tables guide, for others looking to do the same:

Tables\Columns\TextColumn::make('title')->url(fn (Application $application): string => ApplicationResource::getUrl('edit', 'record' => $application->id])),

KB
Kurt Bauman ✓ Link copied!

I have 3 stats widgets. One for Income, another for expenses. Is there a way to calculate the difference between the to for a third widget called Net Income? Trying to learn how to do basic math within a widget. Thank you!

M
Modestas ✓ Link copied!

Load everything into variables before the return [ and simply do the math with variables there :)

It looks like a basic operation to me, so I'm not sure what issue you are having. Maybe add some code where I could guide you to the final result

KB
Kurt Bauman ✓ Link copied!

Thank you for your help. I'm still fairly new and learning just how much I still don't know :) This site is amazing and a very good tool for someone just starting out like myself.

M
Modestas ✓ Link copied!

We all had to start somewhere! But don't worry, the road ahead will be fun once you get over a few bumps :)

KB
Kurt Bauman ✓ Link copied!

You helped me! I took what you said and applied it to an online example that wasn't working before. It works perfectly. Thank you again.

KB
Kurt Bauman ✓ Link copied!

Can anyone suggest how to use trends and filter by say, company_id? This probably is easy to do, and I did a lot of searching, but couldnt find anything. This site is amazing and is helping learn Filament, but I'm learning that I have a long ways to go to getting good. Thank you.

M
Modestas ✓ Link copied!

This might help you: https://laraveldaily.com/post/filament-dashboard-widgets-date-filters

It's not for the company_id, but you can change the date filter to the company filter as the logic is the same.

KB
Kurt Bauman ✓ Link copied!

I'm getting somewhere with this. I just solved the problem and wanted to share my solution. This allows Trends to query just about anything (including company_id for multi-tenancy applications).

$data = Trend::query( Accounting::query() ->where('company_id', $tenant->id) ) ->dateColumn('date') ->between( start: now()->startOfYear(), end: now()->endOfYear(), ) ->perMonth() ->sum('amount');

:)
KB
Kurt Bauman ✓ Link copied!

Has anyone ran into a situation where the trend data is not relyable? I have a table with many rows. If I use trend to get a count of records by month, for example, and show the number in a chart based on 12 months, the data will change each time I hit refresh. This is hapening on my local enviroment, as well as VPS (server is maxed with ram & cores). I've tried the tricks of slowing down the chart to give the system time to preform the query with no effect on the outcome. If I'm expecting a count of 88, I probably get the correct(88) 1 out of 20 times that I hit refresh. Any help would be greatly appreciated. I created a workaround but struggle to understand why my code works and Trend is having issues.

Thank you :)

M
Modestas ✓ Link copied!

It should be reliable as long as your query is reliably made.

In your case, I would check what kind of query it makes to the database and debug from there

KB
Kurt Bauman ✓ Link copied!

This is really odd. I have two charts, one income, and the other expense. The income gets read first and it is always good(it is on the same page and next to the chart with the issue). The expense is the exact same query except for the table being read. If I do nothing but watch the chart, the bar jumps to values that are equal a partial query. I know that the auto-updating is a function of the chart, but it seems to only read part of the table and almost all times, it does not query 100% of the date. Even if I hault the auto-updating, or add a delay, the chart is almost always the wrong value. I can share a private link, this is must unusable. Most of my laravel journey has been learning what I dont know, this seems like it isn't caused by an error with my code. This is my query..

$tenant = Filament::getTenant();

$expense = Trend::query(
AccountPayable::query()
->where('company_id', $tenant->id)
)
->dateColumn('date')
->between(
start: now()->startOfYear(),
end: now()->endOfYear(),
)
->perMonth()
->sum('amount');
M
Modestas ✓ Link copied!

Hmm, this seems to be okay, but... what is the type of your amount? Is it float by any chance? :)

I would honestly install telescope https://laravel.com/docs/10.x/telescope - find the query and try to run it in the database client. This could give you an idea if the results are correct (and I suspect that there is something funky going on with that)

H
horaciod ✓ Link copied!

I struggled to find information on how to add a link to the "Stat" It's not in the documentation either.

Stat::make('Instituciones', Institution::count())
->description('Instituciones')->color('success')
->descriptionIcon('heroicon-m-building-library')
->url(route('filament.app.resources.institutions.index')),
```

We'd Love Your Feedback

Tell us what you like or what we can improve

Feel free to share anything you like or dislike about this page or the platform in general.