Understanding Table Actions0:00
Okay, now let's talk about table actions. And now that we can visualize our data, we can see it, how do we interact with it? So, when we're talking about actions with a FilamentTable, there's really three types of actions we can talk about. When you generate a resource and when you generate a FilamentTable, they default come with these two different kinds of actions. So, what is an action, just regular action? Well, if we go to the browser, we can see we have an edit action, which is right here. So, an action is defined on a row, and it passes in the record, and we can do something to that individual record.
Editing via Modal/Slideover0:27
which is right here. So, an action is defined on a row, and it passes in the record, and we can do something to that individual record. So, in this case, we can edit this record. And what this action specifically does is it goes out to the edit page. Now, one thing that I really like about Filament is I don't always love going out to a page to edit something, especially if it's a relatively small record. And talks are somewhat small, but if we don't want a page, we can actually come down here and just get rid of the edit page entirely. And when I come back here and I click the edit button,
we can actually come down here and just get rid of the edit page entirely. And when I come back here and I click the edit button, instead, it's a modal, and we can interact with it without leaving the page. So, that's kind of nice. But I also, I don't love a modal. To me, a modal should have one, maybe two things at most. If it's any bigger than that, I like it to be a slide over. So, we can actually change this edit action to open in a slide over. So, we do that. We go back, and when we click edit,
to open in a slide over. So, we do that. We go back, and when we click edit, now we have a slide over. And to me, this is a much better user experience. I don't have to go to a new page. I can do what I need to do right here. So, this is really nice as far as your edit action on a single row. Now, of course, editing is not the only thing you might want to do with a row. You might want to, let's say, all these talks that have been submitted, I want the ability to approve a row right here from the table. So, I can do that, and what I would just do is pass in
Adding Approve Row Action1:42
I want the ability to approve a row right here from the table. So, I can do that, and what I would just do is pass in a standard action. So, let's make sure we get the FilamentTablesAction class, and we'll make it, let's give it a unique name. This is especially important when you start writing your tests. We'll call it approve. We need to create an action method here. We're going to pass in the record itself, and then we can do whatever we want in here. So, let's say we have record approve.
itself, and then we can do whatever we want in here. So, let's say we have recordApprove. Again, we can type in this just to make sure we know what we're talking about. This is a Talk, and then if we go to the Talk, let's add a public function here to approve it. So, we can see in this case, we would set the talk status to approved. We would save it. We might want to do other things, like email the speaker telling them that they were accepted.
email the speaker telling them that they were accepted. We could also do anything else we want to do, but this is a nice way to extract that logic out of live>ing on the table itself and putting it in the method. So, right now it's simple. We're just going to set it to approve and save. If we come back here, now this will work. And if we go to the browser, refresh, we can see we have a link here to approve. Now, the edit action has an icon. Maybe we want to add an icon as well.
to approve. Now, the edit action has an icon. Maybe we want to add an icon as well. So, we just pass an icon and let's do the Heroicon check circle. So, refresh. There we go. Maybe we want the color to be success. There we are. So, this is nice. We can approve. And let's take one of these that is submitted. Let's go ahead and approve. And you can see it happens. It's a Livewire request. It goes out in real time. The table
Post-Action Notifications3:18
Let's go ahead and approve. And you can see it happens. It's a Livewire request. It goes out in real time. The table is refreshed. So, you don't have to worry about passing events or anything else. The table will just update with whatever changes were made. Now, right now, the only indication that this was actually approved was the fact that the label changed. We might want to change that as well. And so, after an action is complete, we might want to use this after. And we'll pass in a closure. And now we can send a custom notification. So, we're getting into the notifications package.
And we'll pass in a closure. And now we can send a custom notification. So, we're getting into the notifications package of Filament now. So, we'll do a notification. Remember to make sure, again, the namespace is in Filament and not your standard Laravel notifications. So, we'll make a success notification with a title. And we can also add a body. And maybe this will say the speaker has been notified. You know, whatever else.
And maybe this will say the speaker has been notified. You know, whatever else that action does. So, we go back and let's approve another one here. And that didn't work. And the reason why is because when you do notifications, you do have to send them. So, let's make sure we send the notification. Come back here and let's approve this one. And there we go. We have this nice notification. It's going to live here for a while. I can dismiss it. Or if you want to customize how long the notification stays,
here for a while. I can dismiss it. Or if you want to customize how long the notification stays, you can pass in a duration. So, let's have it show up really short. Let's do that. Let's approve another one. It shows up just for a second and then goes away. So, now we may also want to reject a talk. Let's implement that really quickly. I'll just copy all of this because it's going to be very, very similar. And this is reject. Let's get a different
because it's going to be very, very similar. And this is reject. Let's get a different heroicon. Let's do the no symbol. We obviously want the color to be danger. We're going to reject here. And this is going to be a danger. So, the talk was rejected. And the speaker has been notified. That's probably enough. Now, all we have to do is go implement that reject.
And the speaker has been notified. That's probably enough. Now, all we have to do is go implement that reject functionality in the Talk model. So, let's do this. Okay. So, if we refresh the page, we now see we have this reject action. And let's go ahead and reject this one. And it's been rejected. We got the notification. Everything works. Now, a couple more things we might want to do. Maybe we don't want to accidentally reject someone. And so, we want to add a confirmation.
we don't want to accidentally reject someone. And so, we want to add a confirmation. So, we can just say requires confirmation. Come back here. And if we were going to reject this one, we're going to get a nice modal. Now, this is a case where obviously a modal works better than a slide over. Are you sure you'd like to do this? And we can confirm or cancel. If we cancel, nothing happens. If we go back, try again, and we confirm it. There we go. We got our notification. Everything's good. I will say this is getting pretty cluttered over here.
Grouping and Hiding Actions6:06
There we go. We got our notification. Everything's good. I will say this is getting pretty cluttered over here. So, Filament gives us a nice way to group all these actions. So, let's do an action group. And it's the tables action group. And now, this is just going to accept an array of actions here. So, let's just take these two actions that we created. Let's cut them here and paste them into the action group. And if we want to leave the edit action by itself,
here and paste them into the action group. And if we want to leave the edit action by itself, so we'll do that, and let's make that go first. So, now if we refresh, this is a lot better. We have the edit, and if we want to take action here, we can approve or reject from there. Now, another thing you might want to do, this talk is already approved. So, maybe we certainly don't want to approve it again, and maybe we don't want to allow it to go from approve to reject. So, we can do some of those things. So, this action,
we don't want to allow it to go from approve to reject. So, we can do some of those things. So, this action, again, you've seen us do this before. We can say, is it visible? Let's pass in a closure with the record. And we can say, only if the talkStatus is submitted. So, now we do that, and we can no longer approve this because it's not in submitted. A rejected one can't be approved either, but when it's in submitted, it does show up. So, we could similarly do the same thing on
Bulk and Header Actions7:18
be approved either, but when it's in submitted, it does show up. So, we could similarly do the same thing on the reject action. And that's going to work the same way. So, this allows us to interact with a single record, but what if we want to interact with all the records or maybe just some records? Let's apply some filters and let's say here are some speakers that I want to do something with. I can click here and I have bulk actions. Now, out of the box,
that I want to do something with. I can click here and I have bulk actions. Now, out of the box, Filament comes with a delete bulk action. There's also actually, if you're using soft deletes, a restore bulk action. So, we can add that in here as well, just so we can see it. And if I do a quick page refresh, when I click on some records for bulk actions, then they show up here as drop downs. And you can actually see in a similar way that we added a group here. These are already
as drop downs. And you can actually see in a similar way that we added a group here. These are already in a group. You don't have to put them in a group. So, if we get rid of that, if you like it to look differently, you can have the individual buttons show up here as well. So, in the exact same way that we were able to approve an individual record, we could add a bulk action here. We'll say approve and of course the action. This is going to accept a closure. So, this actually
We'll say approve and of course the action. This is going to accept a closure. So, this actually takes a collection of records. And so, we can use this collection and do something like records.each approve. And so, now if we go back to our table here, let's clear all of our filters. Show me just the ones that are submitted. There we go. And I can bulk approve all of these.
the ones that are submitted. There we go. And I can bulk approve all of these. And there we go. And now they've moved over to approved. Similarly, if we wanted to add the notification, we probably would. We could chain that on in the after method. And that will just run after all of the records have been approved. Now, the last thing I want to share is there is another type of action that doesn't come default as far as the template that Filament gives us. But, of course, we can just add a header action. So, this is going to accept an
as the template that Filament gives us. But, of course, we can just add a header action. So, this is going to accept an array. And let's add an action here. It's a table action. And let's say this is how we want to maybe export all the data. And let's take an action here. And we'll just ray exporting. And if we go to the browser and take a look, now when we refresh, we have this header action up here. And this, I think, is really nice because some people will make you select all the records that you
action up here. And this, I think, is really nice because some people will make you select all the records that you want and then do an export from here. I don't like that because typically if you're exporting the table, you want to export everything that you're looking at. You don't want to have to go through these steps to choose and do this. So, one thing that might be a little confusing, if I'm exporting from the header, is it the entire database? Or is it just what I'm seeing? And I think it makes the most sense for your users when they click this export button to just get all the records
And I think it makes the most sense for your users when they click this export button to just get all the records that are filtered here. So, let's go ahead and find out how we can do that. We're not going to implement the exporting itself, but we just need to see how can we actually get the filtered record. So, in order to do that, we have to actually pass in the Livewire component, and this will give us access to, let me show you, we've got Livewire, and we have access to this GetFilteredTableQuery. So, this will
LiveWire, and we have access to this GetFilteredTableQuery. So, this will actually give us the exact query that's being run to show us the records that we're seeing in the table. So, if we go to our browser, bring Ray over, and pin it here. So, now if I click export, you can see I have access to the query builder that gives me these seven records. If I do a count here and run it again, you'll see I have the seven that come through from here. So, that shows you that's what you're
and run it again, you'll see I have the seven that come through from here. So, that shows you that's what you're getting. So, we do want to make it a little more clear to our users that that is what's going to happen. So, of course, let's get rid of this, and we can add a nice little tooltip. Okay, so we have a tooltip that explains exactly what's going to happen, and now if we refresh and hover over export, we get this nice tooltip that tells us exactly what's going to happen.
and hover over export, we get this nice tooltip that tells us exactly what's going to happen.
