Customizing Laravel Nova

#laravel

The 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

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.

Laravel Nova indexy view

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.

Laravel Nova indexy view

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.

Laravel Nova indexy view

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.

Screenshot showing Nova index view with a relational field which is a link

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.

Screenshot showing that category is not 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.

Preview animation of the email preview

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.

Did you enjoy this post?

Sign up for my newsletter to stay up to date.

You will receive monthly updates on my latest articles and products. I do care about the protection of your data. Read my Privacy Policy.