Customizing Laravel Nova
#laravelThe latest Laravel product, Nova, has taken the community by storm. The way you can build a simple backend in like no time is astonishing. But still, every project is different, and we need to tweak Nova here and there to make it fit our needs. With this article, I want to provide some helpful tips on how to customize Laravel Nova.
Table Of Content
- Define Which Items to Show on the Resource Index View
- Remove Links From Relational Fields
- Hide Resource From Navigation
- Use the value of one resource field form input to calculate another
- Using Eloquent Observers With Nova
- Testing Nova Applications
I will add more and more tips as I discover them.
Define Which Items to Show on the Resource Index View
The index view is where you can see all the items of the chosen resource. In the example below, you can see all my recipes.
But sometimes you do not want to show all of them to the user. In my example, I only want to list recipes from a specific category.
Luckily, there is an easy way to define what to show on the index list. Every resource extends the base Resource
class. In there, you can find the indexQuery
method.
// Inside /app/Nova/Resource.php
public static function indexQuery(NovaRequest $request, $query)
{
return $query;
}
You can copy this method to your own resource class and override it. Here is what I have used only to show breakfast recipes.
// Inside /app/Nova/Recipe.php
public static function indexQuery(NovaRequest $request, $query)
{
return $query->where('category_id', 1);
}
Just customize this query to only show what you like on the index list.
Remove Links From Relational Fields
By default, relational fields provide a link to the related item. So when you click dinner
from my example, you will get to the category item dinner
.
This is a cool feature, but not always what you want. For example, if you don't want to show categories as a resource, it makes sense to skip the link as well. In earlier versions of Nova, I needed to override the Vue component to remove the link. I'm glad there was a method added called viewable
.
// Inside /app/Nova/Recipe.php
public function fields(Request $request)
{
return [
ID::make()->sortable(),
BelongsTo::make('Category', 'category', Category::class)
->viewable(false),
Text::make('name')
];
}
Inside my recipe resource class, I can set the category field viewable to false
. This will remove the link. Now, our category field is just plain text.
Hide Resource From Navigation
Since we don't want to link our recipes to their belonging category, it makes sense to also hide the category recourse from the navigation. This can be done by overriding the $displayInNavigation
property in the recipe resource.
// Inside /app/Nova/Recipe.php
/**
* @var bool
*/
public static $displayInNavigation = false;
Now, we don't see the category resource listed in the navigation anymore.
Use the value of one resource field form input to calculate another
For a project of mine, I have a nova action where the client can approve an event which sends out an email. The action has a field to customize the base content of the approve-email. When the action gets submitted, I send out an email with the custom text.
But now the client wanted to get a preview of the email before the email is sent out. Now here is where it gets tricky. Showing a preview of an email template is quite easy in general with Laravel mailables. But using the custom text from the action field and showing the preview before the action gets submitted is quite complicated. Here you can see the result.
In the end, I used a similar approach to the package Custom Calculated Field by Kyle. The idea is to have broadcast and listener fields. When you enter a value to a broadcast field, the listener receives it through Vue. This is how I was able to create an email preview from the custom email text right in the action form.
It may sound a little bit easier than it is, but Kyle has a great article about it where he explains everything about this approach in detail.
Using Eloquent Observers With Nova
In a project, I was using the created method of an observer to hook into Eloquent to run some tasks after
a Nova resource had been created. Somehow, I ran into some strange behavior until I found out, Nova is using database transactions. This was new to me.
It turned out; there are some different opinions about how events should work with transactions. Fact is, with Nova, the created method of my observer was triggered before the resource was stored into the database.
If you need to make sure events are only being fired after
the database transaction, check out this package. It helped me a lot.
Testing Nova Applications
This is a hot topic. How do you test your Nova application? Not at all? Through the frontend with Dusk? Or Just the Nova API? I don't have found a solution that fits me but there is this Nova application by Braden Keith. He built it using TDD and I find it very helpful.