Switching to FilamentTables0:00
Now that you have a good grasp on FilamentForms, let's take a look at FilamentTables and see how we can visualize the data that we've entered into our database. Now, if you're following along and coding along with me line by line, I did make some changes outside of the video, so I want to go over those really quickly. We'll start with the Speaker model. We actually never added a hasMany, a Speaker has many Talks, so that has been added here. And I also just refactored the qualifications that we had into a constant on the class instead of listing it here. The reason I did that is because I updated the SpeakerFactory a little bit. Number one, to get a random number of qualifications to be set there, and as well, we can add Talks
The reason I did that is because I updated the SpeakerFactory a little bit. Number one, to get a random number of qualifications to be set there, and as well, we can add talks when we factory up a speaker. I also made a few changes to the Talk model. So I added three new fields. We have the length of the talk, we have the status of the talk, and whether it's a new talk as a boolean. So the length and the status are both enums that we talked about before. So you can see the length here is pretty simple. The status is simple here as well.
Installing Debugbar and Seeding0:57
So you can see the length here is pretty simple. The status is simple here as well. And if we go to the Talk model, you can see we've just added these enums and cast those fields to that enum. So if you're coding along, just go back to the video, pause those sections, add this code, and then we can get started. You could also reference this commit in the GitHub repository. All right, and one other thing I want to do is install the debugbar, because since we're using tables, I want to look at some of the queries that are being generated and make sure that we understand what's happening with Eloquent and the queries in the backend.
using tables, I want to look at some of the queries that are being generated and make sure that we understand what's happening with Eloquent and the queries in the backend. So we're going to compose a require the debugbar. Okay, and now that that's installed, we also want to migrate fresh --seed. Now let's go ahead and go into Tinkerwell and use that factory that we just created. And I want to just create 10 speakers, each of them with one talk. So I'm going to run that. And now let's go into the browser. And now you can see we have our talks page here and the 10 talks that we just created with 10 different speakers.
Configuring Table Columns1:45
And now you can see we have our talks page here and the 10 talks that we just created with 10 different speakers. So let's go into our talk resource and take a look at this. So what we have here in the table is the title, we have the speaker name, we have this created_at and updated_at. So a couple things to know about filament tables is if you don't want columns to show, they can be listed as toggleable. If we go back to the browser, you can see I can click here and add created_at or updated_at now, I'm not too worried about those columns. So I'm going to go and just delete those.
at now, I'm not too worried about those columns. So I'm going to go and just delete those. And so I'll save that, go back to the browser. And so you can see what we have here is the title of the talk, and we have the name of the speaker. And just so you know, the speaker is actually a related model. It's not on the Talk itself. And so what you can see here is we have dot notation. And so this is a relationship. And using this dot notation, we can pull in data from that related database table and
Avoiding N+1 Queries2:29
And so this is a relationship. And using this dot notation, we can pull in data from that related database table and bring it in here. Now, I'm not sure why numerics here, let's get rid of that. But you can also see that this is sortable right now. So if we go back to the UI, and if we click here on the speaker, you can see that it actually will sort even though it's a related database table, Filament is smart enough to know how to update the query so that it will sort based on this related table and the specific field in that table. Now, the reason I wanted to download the debugbar is because in a normal Laravel app, if
in that table. Now, the reason I wanted to download the debugbar is because in a normal Laravel app, if you were doing this, and you took a related model and wanted to get the name off of it, that would introduce an n plus one issue. And you would have 10 queries, each for one speaker to go find the name. But you can see in our queries, there's actually only four. And the speakers or the eager loading that needs to be done to make sure that you're not running too many database queries is actually handled by Filament. So if you're wondering, well, how do I make sure I modify all my tables to make sure they're performant and not doing n plus one, Filament takes care of that for you, which is really
So if you're wondering, well, how do I make sure I modify all my tables to make sure they're performant and not doing n plus one, Filament takes care of that for you, which is really nice. So let's close that out. And another thing that is good to note is not only can columns be sortable, they can also be searchable, or we already have searchable on the title. We can make this sortable as well. And now we go back to the browser, so we can sort on either the title or the speaker. And we can also do a search here. So if I do Giovanni, I have indication here of what filters are being applied.
Adding Descriptions and Avatars3:54
And we can also do a search here. So if I do Giovanni, I have indication here of what filters are being applied. It's a search filter in this case, and it's pulling back the right record. So very easy to make your tables really interactive, being sortable and searchable, even on those related database fields. So now let's add a couple more columns to this table and see what else we can do with Filament. If we come back here, let's add a column for the abstract. And this is what holds the description of what the talk does. So we go to the browser.
And this is what holds the description of what the talk does. So we go to the browser. So you can see, because this is a very long description, it's actually making our table scroll. And we probably don't want that. So what we can do is go back to here, and we can pass in wrap here. And when we do that and go back, now when we refresh the table, you can see that we wrap it so that it fits on one screen, which is really nice. Now these abstracts could be even longer, and they could take up more space. So maybe we don't want to show the whole abstract, but maybe we do want just a little preview.
Now these abstracts could be even longer, and they could take up more space. So maybe we don't want to show the whole abstract, but maybe we do want just a little preview of what the abstract might contain. So let's look at how we can do that. Maybe instead of having its own column, let's have the abstract kind of as a sub-description under the title. So we can do that easily here. We can have a description. And inside here, I want to pass a closure. So we're going to pass the record into the closure here.
And inside here, I want to pass a closure. So we're going to pass the record into the closure here. And we can even type hint this, so we can say talk, just to give our IDE some indication of what we can do here. And so we could return the entire abstract. Let's get rid of this one and refresh the page. And again, we've got this problem where the side scrolling is too much. So let's go back. And instead of returning the entire thing, let's use Laravel String Helper, and let's just limit it to maybe like 40 characters or something.
And instead of returning the entire thing, let's use Laravel String Helper, and let's just limit it to maybe like 40 characters or something. So now if we refresh, this is much nicer. So we get kind of an indication of what the abstract is. If we wanted to click through and see more, we can do that. But this description is really helpful when you have different data that's related to each other, and you want to combine them into one column, using that description method is really nice. Now, in the last video, we just worked on adding images to speakers. And so what if we want to pull in the image or the avatar of the speaker on this table?
Now, in the last video, we just worked on adding images to speakers. And so what if we want to pull in the image or the avatar of the speaker on this table? Well, that's pretty simple. We can, let's put it before here, we'll do an image column. And let's make speakerAvatar. And if we go back to the browser and take a look, looks like the label is wrong. So we're going to need to update that. And also, nobody has an avatar yet. So let's go into the speakers. Let's pick one of them.
So let's go into the speakers. Let's pick one of them. And let's add an avatar here. All right, I'll go ahead and save that one. And now if we go back to the talks, you can see now we have the image coming in for that speaker. Now, some people don't have an avatar, and maybe you want to set a default. So it's not just empty, we can do that as well, by having defaultImageUrl. Now this could be, you know, maybe an asset that you're storing locally, or one of the things I like to do, let's pass the record in here as well, and go out to the internet.
Now this could be, you know, maybe an asset that you're storing locally, or one of the things I like to do, let's pass the record in here as well, and go out to the internet and get a custom avatar that maybe just takes the name and gives the initials or something of the name. So there's actually a website that you can do that from, it's called this UI avatars, I just pasted this in here. And you can set the background color, and we are just URL encoding the speaker name. So when I do this, and go back to the browser and refresh, I can see I have just the initials. And so that gives me something that kind of indicates who they are, if we don't have an image of them.
And so that gives me something that kind of indicates who they are, if we don't have an image of them. Now, I don't like that this is a box. I'd like to make it a circle. And as you can probably imagine, all we have to do on this image column is pass in circular, come back here. And now this looks really nice. We also forgot to update the label. So we can always pass in a label here. And we'll just say, speaker avatar.
Inline Editing and Badges7:42
So we can always pass in a label here. And we'll just say, speakerAvatar. Okay, so we added a few new columns to the database at the beginning, one of them was whether this is a new talk or one that's been done before. So let's add that to the table as well. We can come in here and use what's called an iconColumn. So let's do the iconColumn, and we'll make newTalk. And so this is the Boolean from our database. And because it's a Boolean, let's just pass Boolean as a method chained on to the iconColumn here, go back to the browser.
And because it's a Boolean, let's just pass Boolean as a method chained on to the icon column here, go back to the browser. And you can see that we have this nice checkbox. And if the new talk were not true, we would get a little x, we can actually go into the database itself here, let's just change this to 0, and refresh. And there we go. So you can see that it is, we get the indication whether it's a new talk, yes or no. The other thing we could do is actually make this inline editable. So instead of just having an icon column, we could make this a toggle column. And so let's get rid of the Boolean.
So instead of just having an icon column, we could make this a toggle column. And so let's get rid of the Boolean. And if we refresh again, you'll see that we have these toggles. And if I want to inline edit without pulling up the talk or anything, I can just come in here and say, that's a new talk, this one's not. We check our database. And we can see now that that was updated. All right, before we go any further, I do want to go into my .env file and the debug bar is slowing things down a little bit. So I'm just going to change this to false and go back to my browser.
debug bar is slowing things down a little bit. So I'm just going to change this to false and go back to my browser. And there we go. Everything's working better now. So you can see as we click these, now they're much more responsive. Now this is not the only inline editable column that we have available to us. We could also, let's say we need to update the speaker's name, we can do that as well. So back in our Talk resource, instead of this, or maybe the talk name, let's do that. So instead of this being a text column, we can make this a text input column. And if we want to update the title of the talk, we can do that.
So instead of this being a text column, we can make this a text input column. And if we want to update the title of the talk, we can do that. Now we can't have a description when we have a text input column. So let's just get rid of the description for now. Go back to the browser. And you can see we've got this here. And so if we want to add something here, as soon as we tab out, it's going to go to the database and make that update. Now obviously, we do need to do some validation on this. So we need to go into the code.
Now obviously, we do need to do some validation on this. So we need to go into the code. And we can add our rules here. And this is where you would pass in any of your validation rules that you want. So we can just take those that are accepted. That way we're doing the validation as we're making these inline edits to the table. So we added a few more columns, we have the status of the talk. So obviously it gets submitted, it needs to be reviewed by the LayerVal team to decide whether they're going to accept or reject it. Let's add that one in here as well.
whether they're going to accept or reject it. Let's add that one in here as well. Maybe let's put it at the end here. So we'll say this is a text column. And we're going to say status. But what we're going to add here is a badge method. So let's take a look at what this looks like in the browser. So here you can see we have a badge, which is really nice. It makes it formatted. It looks like it's a badge.
It makes it formatted. It looks like it's a badge. It looks a little bit nicer. So right now everything is the primary color. And even if we go to the database and change one of these to approved, and now back to the browser, it still looks exactly the same as submitted, which isn't what we want. We want some visual indication that this is something different. Because we're using enums and Filament works so well with enums, we can actually go to the TalkStatus class. And let's add a method here.
the TalkStatus class. And let's add a method here. This is a public function for getColor. We're going to return a string. And so we can return a match. And we're going to pass in the different options we have here. And so if it's submitted, let's say that is primary. If it's approved, we'll say that's success. And then rejected is danger. So if we go back to the talk resource where our columns are defined, and on the status,
And then rejected is danger. So if we go back to the talk resource where our columns are defined, and on the status, put this on a new line, we can make it sortable as well, but I want to pass in color. And let's pass in the state of this field, which is the enum itself. We'll just return state::getColor(). If we go to the browser and refresh now, now you can see that the color is defined on the enum, and then we can use that color to change the different look and feel of the badge. And if we go to the database, and let's change one of these to rejected, and go back to the browser, now you can see green, red, and the primary color. So that's a really nice way to have your code nice and clean, and also have the different
browser, now you can see green, red, and the primary color. So that's a really nice way to have your code nice and clean, and also have the different colors available to you as you're setting your badges in the table. Now we also have the type of talk, and maybe for the type of talk, we want to have an icon that will kind of represent what type of talk it is. So let's go ahead and do that as well. So we have a icon column, and this was the length. And so what we do here is we pass in an icon method. We get the state, and let's just return a Heroicon. Let's say for the lightning talk, we're going to do a lightning bolt.
We get the state, and let's just return a Heroicon. Let's say for the lightning talk, we're going to do a lightning bolt. So now we can see we have this icon here, but we want to, of course, make it change based on what the state of the length is. So again, we can do a match here. We're going to return match state, and this would be talkLength normal. We'll say that's going to be Heroicon::megaphone. If it's lightning, we'll do the bolt. And then if it's a keynote, we'll do a Heroicon::key. And let's go to the browser, refresh.
And then if it's a keynote, we'll do a Heroicon key. And let's go to the browser, refresh. And they're all returning megaphones because they're all the same length. If we go to the database directly, let's change this one to a keynote. And of course, this one will be lightning. And if we refresh, now we can see if we want to have an icon that indicates what length it is, we can do this as well. So let's just clean this up a little bit, and then we'll be done. I don't think we actually need the title to be a text input column. So let's just call this a text column again.
I don't think we actually need the title to be a text input column. So let's just call this a text column again. We don't need the rules. And let's bring back the description. There we go. So I think this looks really nice. We've got the title. It's searchable. We can see who the speaker is. We have some inline editing where we need it.
We can see who the speaker is. We have some inline editing where we need it. We have badges. We have icon columns. And of course, if we reference the filament docs really quickly, there are a few other columns we didn't go over. You can do a select column as an inline editable column as well. And then there are also advanced columns if you need to build your own column because what filament has doesn't work for you.
what filament has doesn't work for you.
