BLACKFYRE
MG—01
LANG
←
ALL POSTS
05 · Writing / 2021
07 JUL 2021 · 2 MIN READ

Context aware table row actions for Laravel Nova

Nova's table row actions don't know which row they're on. Hand them the row's model with a fluent setter, and shape each action's form to it.

CONTENTS
03 +

During one of our dev runs, there were some fancy action requirements, and I was really happy to find that Laravel Nova supports actions on the index table rows!

So imagine how bummed we were when we found out that said actions don’t really know anything about the contents of the table row they’re sitting at… even though it works just fine on the resource detail screen. But, as always, there’s a way, and you don’t even have to install a third-party library to solve this!

You only need to do a couple of things. It’s so easy that you’ll be facepalming for the rest of the week!

Give the action a resource

First, you’ll need to create an attribute on your action with a fluent setter for it:

app/Nova/Actions/EmailAccountProfile.php
PHP
1<?php
2
3namespace App\Nova\Actions;
4
5use App\Models\AccountData;
6use Illuminate\Bus\Queueable;
7use Laravel\Nova\Actions\Action;
8use Illuminate\Support\Collection;
9use Laravel\Nova\Fields\ActionFields;
10use Illuminate\Queue\InteractsWithQueue;
11use Illuminate\Contracts\Queue\ShouldQueue;
12
13class EmailAccountProfile extends Action
14{
15 use InteractsWithQueue, Queueable;
16
17 public $resource;
18
19 /**
20 * Perform the action on the given models.
21 *
22 * @param \Laravel\Nova\Fields\ActionFields $fields
23 * @param \Illuminate\Support\Collection $models
24 * @return mixed
25 */
26 public function handle(ActionFields $fields, Collection $models)
27 {
28 foreach ($models as $model) {
29 (new AccountData($model))->send();
30 }
31 }
32
33 /**
34 * Get the fields available on the action.
35 *
36 * @return array
37 */
38 public function fields()
39 {
40 return [];
41 }
42
43 public function setResource($value)
44 {
45 $this->resource = $value;
46
47 return $this;
48 }
49}

Hand it the row

Second, when you’re adding the action to your resource, just set the resource on the action, like this:

app/Nova/Account.php
PHP
1/**
2 * Get the actions available for the resource.
3 *
4 * @param \Illuminate\Http\Request $request
5 * @return array
6 */
7public function actions(Request $request)
8{
9 return [
10 (new EmailAccountProfile)
11 ->onlyOnTableRow()
12 ->setResource($this->resource),
13 ];
14}

Inside a Nova resource, $this->resource is the underlying Eloquent model, so for a row action it’s the model of that row.

Using it in the form

With the model on the action, fields() can build the form for that particular row. For example, telling the user where the profile is going:

app/Nova/Actions/EmailAccountProfile.php
PHP
1use Laravel\Nova\Fields\Text;
2
3public function fields()
4{
5 return [
6 Text::make('Note')
7 ->help('The profile goes to ' . optional($this->resource)->email . '.'),
8 ];
9}

The optional() keeps the form from breaking if the action is ever built without a row behind it.

With this, you can customise each action’s form to the requirements of the actual row, much like in the detail view!

TAGS
Laravel
Nova
PHP
06 · CONTACT

Have a system that needs building?

GET IN TOUCH → PROJECTS →
PRODUCT DATA SHEET
MG—01
BLACKFYRE
S/N MG-1985-1027
Miklós Galicz — Golang Advocate · Solution Architect
MODEL
MG—01 "Miklós Galicz"
SERIES
1985
ORIGIN
Nagykovácsi, Hungary
FUNCTION
Senior Full Stack Engineer · Solution Architect
CORE LANGUAGES
Go · PHP · JavaScript
SPOKEN
Hungarian · English · German
SERVICE LIFE
~20 years in software, ongoing
POWER SUPPLY
Coffee, 2–4 cups / day
DIMENSIONS
1 × human, standard size
OPERATING TEMP.
Calm under production incidents
CONNECTIVITY
[email protected] · github.com/blackfyre · linkedin.com/in/galiczmiklos
Less, but better. Specifications subject to continuous improvement.
● ● ●
MG—01 · SERIES 1985
№ MG-1985-1027
CERTIFICATE OF OPERATION
Certified Operator
Has located every documented feature of the MG—01 without reading the manual. Probably.
TIME
—
FEATURES
—
DATE
—
SIGNED
Miklós Galicz