How to avoid showing all widgets on all dashboard pages?
Hi, I want to create multiple dashboards, each with their own specific widgets. I have this kitchen dashboard for example:
This dashboard shows all my widgets in
app/Filament/Widgets/
, as if BaseDashboard
automatically fetches and returns all existing widgets. How can I avoid this, and select which widgets should be shown on which dashboards?24 Replies
Move the widgets to a different location so they aren’t auto registered and register them manually in each panel service provider with ->widget()
Thank you! But I only have one panel, and therefore only one app/Providers/Filament/AdminPanelProvider.php. I have multiple dashboard pages within the same panel.
Should I register all of my widgets in this service provider with
->widgets([])
?Hmm, multiple dashboards doesn’t make sense to me. In that case it sounds like you need to run checks in each widget that determines if the widget can be shown based on the panel’s id which you can get from the FilamentManger facade.
Hmm.. Would you create multiple panels if you have a filament app for a food producing and delivery business, if the kitchen, the office, the couriers etc. need their own dasboard page, or would you just create multiple dashboard pages? I like the thought of separate panels, but I don't want to add complexity for no good reason.
The documentation mentions multiple dashboard pages here:
https://filamentphp.com/docs/3.x/panels/dashboard#creating-multiple-dashboards
But the details of how to choose which widgets to show on which dashboard is, AFAIK, not documented.
But I did just try to overwrite the getWidgets method from the
Filament\Pages\Dashboard
class:
like this in my KitchenDashboard page:
Which seems to give control over which widgets to show on each dashboard page, but I am not sure if this is the recommended way.There’s no real right or wrong way. Personally, if the 3 groups have different levels of access I would make separate panels. But the getWidgets method will work as long as they aren’t in the auto discover path in the panel service provider.
So, you could use the auto discovery path for widgets that are shared across each one, and just make context aware widgets in a different directory and include them with an array_merge in each dashboard with the getWidgets method.
Maybe I should look more into multiple panels, as I like the idea of keeping different access levels separated to their own space, instead of defining access on each page. But how does filament know what panel to show to which user? And can users jump between panels? Where can I read in-depth documentation about multiple filament panels? I feel like I need to expand my knowledge on multiple panels before I start playing with it.
Re. dashboard widgets, I do not think the widgets need to be moved out of the auto discovery path when overwriting the getWidgets() method, it just seems to work.
If you are overriding the methods the auto discover won’t matter unless you have widgets that you want to show regardless of the panel in which case you’ll want to consider a merge.
For panel access that could either be handled with a middleware based on user role / permission or via the canAccessPanel method on the user model.
If a user can access multiple panels, will there be a panels switcher at the top of the panel pages? Or is it simply a question of navigating to the specific panel url?
Filament doesn’t know what panel to show other than what panels you tell it too.
Not natively, but there is a panel switch plugin.
So it is basically completely separate "admin" panels, like starting from scratch basically?
In a sense, yes.
But the resources are kept the same, in the same folder structure etc.?
Or wait, no they can't be the same.
But everything is reusable across panels. It’s just how OOP works. Each panel can register resources in the same way you can register widgets to each dashboard.
It can be. That’s the beauty of it.
But now as soon as I add a resource, it appears in my standard admin panel. If I then create a kitchen panel, I would expect that the same resources would appear in the same manner, basically resulting in no difference between the panels. But logically, the panels should show different resources, right? Like some resources should be shown to admins, and others for the kitchen staff.
I know I can add resource and page access logic, but then the users would be able to access different resources based on their roles, regardless of whether the same or multiple panels are being used.
Right but this is where the auto discovery comes into play. There flags you can pass the make commands to put them under specific panels for auto discovery, but it sounds to me that you need to abandon the auto discovery and load the manually where they are needed. It’s not wrong, just a use case for your app.
If a resource isn’t registered with a panel then it won’t even exist under that panel.
Where do I see what resources are registered with which panel?
They are either auto discovered based on the path or you define them in the panel service provider.
For instance if you remove ->discoverResources() from a panel service provider then it won’t have any resources at all.
And you can register them with ->resources() instead manually.
Ahhhh, it clicked now.
Access to those resources should be defined by the model policies at that point.
Yes, I use filament shield for roles and permissions, and model policies as well.
Thanks a ton, this was very helpful!
Hopefully it all makes a little more sense now. But there’s no right or wrong way, just what’s optimal for your app. And understanding there’s more than one way to accomplish the goal.
Even with filament it’s all still just laravel. 🙂
@nowak FWIW, my app has a main dashboard and 4 additional dashboards grouped under an "Analytics" navigationGroup. The analytics dashboards have their own collections of widgets that have specific filter form criteria and are tailored to specifc types of data / Models. All you really need to do is override the getWidgets() method in your Dashboard classes to include only the widgets that you want. If you want Shield permssions for individual widgets ( not just the Dashboard pages ) then you'll still need to register all of them in your panel provider. I also have my Models ( and their Policies ) in sub-folders by functional area, with Resources and Widgets following the same structural pattern.
Thank you for sharing! And thanks for the detail about still needing to register widgets in the panel provider for shield permissions to work with individual widgets, very useful!