Tabbed container with infolist in one tab, other related tables in the other tabs
Hi folks! Huge fan of Filament (tho I'm very new). Sorry for the n00btastic question, but googling didn't get me where I needed to go. I'm trying to build a tabbed interface where the first tab is the model's general iinfo, and the tabs are populated with already established $table schemas from other models. I'm sure I'm missing something super obvious, but would appreciate a nudge in the right direction.
44 Replies
What I really want is to be able to re-use the model's table definition without haviung to recreate it every time I want to display the related table
(I'm probably always going to want that table to look the same and have the same functionality, and I don't really want to have to duplicate that each time I display it)
Something like
MyModelResource::table()
or somesuch
I'm 100% sure I'm overlooking something super obvious. Have only been working with filament a few days, so a little lost
I'm looking for the infolist style of tabs, where the container spans the full width and the tabs are on top, versus the filtering-styleThis could be useful. I haven't tried this yet but just thinking of ways to do this. You could create a livewire table for each model that could be reused anywhere. They can be used in infolists so you could possibly combine with your tab layout.
Add Livewire component to infolist: https://filamentphp.com/docs/3.x/infolists/adding-an-infolist-to-a-livewire-component
Adding a table to a Livewire Component:
https://filamentphp.com/docs/3.x/tables/adding-a-table-to-a-livewire-component
Follow the instructions above. Then, in your tab do something like this , and then in that view
Thanks to both of you - that helped! Now just need to figure out how to pass the current user into the component query so only their items are shown when looking at their details page
Glad that helped. I'll have a use for this too so it was very useful research.
Query scopes would probably help there and you could also use modifyQueryUsing for the table query.
https://filamentphp.com/docs/3.x/tables/filters/query-builder#scoping-relationships
https://filamentphp.com/docs/3.x/tables/grouping#customizing-the-eloquent-query-scoping-behavior
I think the latter is probably what you want here but you could also do it on the model with a regualr query cope if this is application wide and not just specific to these tables.
Yeah, it's a pretty complex application where I don't want to duplicate table schemas, so I need them to be re-usable. (Users can have assets, accessories, licenses, etc - all of which are first class models/resources, and we'll want to see which users have those assets, licenses, etc from those tables as well)
Right now I'm playing around with pulling the main table definition from AssetResource through to the other resource I had to make. But if trial and error right now, but always making sure the tables display the same (even if we add a column, etc) across all places they could be is critical
This is all a pretty big experiment - the existing codebase is 11 years old, so trying to see if Filament is the right tool for the job or if we should stick with what we have. There's nothing exactly wrong with what we have, but Filament would hopefully allow us to move a little more quickly once it's all set up
Like, this almost works:
People who can see all of the assets, (accessories, etc) within the system should see the largely unscoped view, while looking at a specific user, you should only see what's assigned to that user
I was hoping that something like this would work:
but that relationship doesn't seem to be scoping it properly
So I think query scopes on the models in question would handle showing the right data to solve that part at least. https://laravel.com/docs/10.x/eloquent#query-scopes
You could have conditional logic based on the authenticated user and if you use
spatie-permissions
you can use roles. I use Filament Shield for an easy GUI to manage roles/permissions in our apps.Laravel - The PHP Framework For Web Artisans
Laravel is a PHP web application framework with expressive, elegant syntax. We’ve already laid the foundation — freeing you to create without sweating the small things.
The relations already exist on the model (user has an assets() relationship, etc)
I'll definitely check that out, thanks - I haven't seen Filament shield. We have a very old bespoke permissions system, from before Laravel had a lot of nuanced support. (This was originally built on Laravel 4, and we've been upgrading, but not everything got the full overhaul)
In the code above for that ViewEntry bit, since it references the assets() model method, would do it, but it seems not
Assuming I understand you correctly, the raltionships should be fine as is. The query scope modifies the base query for everything on that model and will return only the results from that relationship based on permissions. So you add a global scope method to your model and in there you can check your custom permissions and return the query modifier you want.
I'm not even using permissions right now lol
Jusr trying to see if I can get the widgets and panels and etc to behave the way I want
I can pull over permissions later
But that
ViewEntry::make('assets')->view('livewire.view-asset')
is on the UserResource
, which uses User as the model, so I kinda don't know why it's not loading just the assets scoped to that user in the resulting table
(Again, I'm super new to Filament. I appreciate all of the suggestions)
I don't even know if this is the right solution yet. Have heard some murmurs about performance with a lot of data, and we definitely have a lot of dataAh, gotcha. Could you post your livewire.view-asset related code and the User model? I suspect it's somewhere in that area.
As a test, can you add a text field and just dump the assets from within the infolist/page you are using? WIll help narrow it down.
Lots of data can be a performance thing, but I had almost a million records in a table with like 30 fields + relationships with no real issues (unless you try to view them all at once lol).
Not sure if that's a lot either haha.
The user model method is:
Livewire view-asset is just:
list-assets is just:
It's been a while since I've felt like this much of a n00b lol
lol. The front end parts make me feel like a n00b all day every day.
There should be one more file for the livewire component, I think. Check in app/Http/Livewire for the list-assets related php file and share that.
There is:
ListAssets:
Again, I'm trying to do some clever table re-using
The structure of Filament alone is enough to make anyone feel like a noob. So many resource files
Our DB structure is also pretty hairy, as we use a lot of polymorphism
Legacy code is always fun lol. I've got some that I really need to clean up too.
I like the table reusing, that's a good idea. I was going to ask next about the inverse and relationship, that's where I thought the problem might be.
Have you tried including the table directly, just to rule that aspect out?
I'd sort of expect the scope to go in the ListAssets bit, but I don't have access to the $record->id there
I haven't yet - so far been doing a lot of poking and hoping lol
lol. Try a simple table there just to rule that out. I think you are close, I feel like this should work.
You can get acess to
$record->id
in the mount method in the php file for the livewire compontent like this: https://filamentphp.com/docs/3.x/infolists/advanced#accessing-the-current-record-in-the-livewire-componentAnd speaking of n00b, learning filament has been a humbling experience lol. I don't know where Livewire ends and Laravel begins, not to mention Alpine. I'm loving it now that I know it a lot better but I'm still trying to learn it much deeper.
Yeah, me too. This is like day 5 for me, and seeing where one ends and the other begins is a lot
Been working with Laravel since v4, but v11 is even different than v8 (which our legacy codebase is on)
"Target [Illuminate\Database\Eloquent\Model] is not instantiable." 😢
I'm not even lying, I have like 400 tabs open for different parts of filament right now
haha. I always do!
Scoping is working on that ListAssets livewire php page.
shows me the assets for the logged in user - which at least means I'm not completely crazy
But I get that mounting error if I try to use the model + mount() method there
So you added the mount method to the
class ListAssets
file? Try removing mount and just doing public Model $record;
. But thinking about that, it just makes it available to the livewire component. I assume you want to pass it into the query?Yeah
Do you have
->record($this->user)
in your Infolist declartion? https://filamentphp.com/docs/3.x/infolists/adding-an-infolist-to-a-livewire-component#passing-data-to-the-infolistI bet I don't
Hm. "Using $this when not in object context" error
I have my infolist on the UserResource tho
That's where I have the tabbed UI and pull in the liveewire table component
So I'm extending the Resource in that file, not the Component
Ah, right. So in UserResource you should have access directly to $record. I'm using it like that in some of mine, eg:
Forms\Components\Textarea::make('errors')
->formatStateUsing(function ( $record ) {
return str_replace( ",", PHP_EOL, $record->errors );
})
Since this was a closure, I had to pass it in.
I do that in a few other places there (making the urls in the profile, etc) but I couldn't see how to attach that query to the ViewEntry
Can you post the UserResource code?
In your Livewire view-asset try something like: <livewire:list-assets :user="$user"/> or whatever model you have set for that table in mount
Ugh, I've changed so many things now that I'm not sure where its broken
@Chrispian It's here: https://github.com/snipe/filament-snipe-it/blob/main/app/Filament/Admin/Resources/UserResource.php
GitHub
filament-snipe-it/app/Filament/Admin/Resources/UserResource.php at ...
Experimental - do not use. Contribute to snipe/filament-snipe-it development by creating an account on GitHub.
(It's very long, sorry)
https://github.com/snipe/filament-snipe-it/blob/9d375ab631722639f58ee630a7ed466550c0b3f8/app/Filament/Admin/Resources/UserResource.php#L109-L114 <-- that's the bit where I invoke the livewire
GitHub
filament-snipe-it/app/Filament/Admin/Resources/UserResource.php at ...
Experimental - do not use. Contribute to snipe/filament-snipe-it development by creating an account on GitHub.
Getting closer 🙂 Now the table loads with nothing in it lol
IDK if its a problem but you don't need this file: https://github.com/snipe/filament-snipe-it/blob/main/app/Livewire/ViewAsset.php You can have the view entry without a component
GitHub
filament-snipe-it/app/Livewire/ViewAsset.php at main · snipe/filame...
Experimental - do not use. Contribute to snipe/filament-snipe-it development by creating an account on GitHub.
try $getRecord() <livewire:list-assets :record="$getRecord()"/>
where :record is the name of the model from your resource.
If I dump out
$getRecord()
in the LW component, it does seem to show the correct record - just having a helluva time including it in the query
I think I farted up some of the stuff in the resources
The current version of this software consumes our own API via bootstrap tables, so it's a bit more confusing to think about this stuff from a LW perspective
I really appreciate everyone's time helping me - you folks are the best. If you're ever in Portugal, I'll buy you a ginginha or an imperial 🙂
Where I think I'm messing this up is how I'm approaching the filter query.
if I do that, I need the record ID, so I'm back to being boned.
If I do it from the user search:
the sorting and filtering get screwy where it's trying to sort on asset fields against the user table
We alreadsy account for those sorting scopes in our API, but we're not using our API for that, so all is goofed up
(Since those sorts are being done on the query reults that are being passed, and that is a user object, which wouldn't have purchase_date
, etc on it.)I'm gonna stew on this some more. I'm invested now lol.
I think I got it working
But oddly, some of my
sortable()
columns arde not sortable anymore
I don't think the Expose tunnel will stay open for long, but https://s5hiupeera.sharedwithexpose.com - email: [email protected], password: password
If you click on the Users tab section and then the assets tab in the users listing
(It's all dummy seed data, of course)
I'm not sure whether I solved it the right way, mind you 😄Nice! Looks good. I see the sorting issue. I'm betting since it's a modified query + a LW component something needs to be done around that to make it update the table data.
"Right way" lol. Never heard of it 😉
Weird that none of the other sorting bonked tho
Probably something really stupid lol
Oh of that I'm 100% certain lol