space_mauve's avatar

Can an inline action link to a filtered Laravel Nova resource

Hello, is it possible to link to a filtered nova resource. For example if two nova resources exist:

Books

Books had a nova filter to display them by a specific genre.

Genres

Genres had an inline action (lets call it "Related Books") that takes the user to the Books resource with the corresponding genre filter already applied.

The bit I'm not sure about is how best to work with the based64 encoded filters param. I could hard code the list of filters/ values in the action, base64 encode them and then send to Action::redirect but this seems messy (and unreliable if additional filters are added in the future).

Any help with how best to approach this is appreciated.

0 likes
2 replies
LaryAI's avatar
Level 58

Yes, it is possible to link to a filtered Laravel Nova resource. One way to achieve this is by passing the filter parameters as query string parameters in the URL. Here's an example of how to do this:

  1. In your Genres resource, define an inline action that redirects to the Books resource with the corresponding genre filter applied. Here's an example:
public function actions(Request $request)
{
    return [
        (new Action('relatedBooks'))
            ->onlyOnTableRow()
            ->canSee(function ($request) {
                return true; // Add your authorization logic here
            }),
    ];
}

public function relatedBooks(Request $request, $resource)
{
    $genreId = $resource->id;
    $filter = base64_encode(json_encode([
        [
            'class' => GenreFilter::class,
            'value' => $genreId,
        ],
    ]));

    return Action::redirect('/nova/resources/books?filters=' . $filter);
}
  1. In the Books resource, define a filter that filters the books by genre. Here's an example:
class GenreFilter extends Filter
{
    public function apply(Request $request, $query, $value)
    {
        return $query->where('genre_id', $value);
    }

    public function options(Request $request)
    {
        return Genre::pluck('name', 'id')->toArray();
    }
}
  1. When the user clicks on the "Related Books" inline action in the Genres resource, they will be redirected to the Books resource with the corresponding genre filter applied. The filter parameters will be passed as a base64-encoded JSON string in the filters query string parameter.

  2. In the Books resource, you can decode the filter parameters and apply them to the query builder. Here's an example:

public static function indexQuery(NovaRequest $request, $query)
{
    if ($request->filters) {
        $filters = json_decode(base64_decode($request->filters), true);

        foreach ($filters as $filter) {
            $query = app($filter['class'])->apply($request, $query, $filter['value']);
        }
    }

    return $query;
}

This code decodes the filters query string parameter, applies each filter to the query builder, and returns the modified query builder.

1 like
cjholowatyj's avatar

@space_mauve did you try the above successfully? Would love to know if this was a genuine solution before devoting the time to implement this myself :D Thanks in Advance!

Please or to participate in this conversation.