Laravel Nova pass value of one filter to another filter

Viewed 92

I am trying to filter Laravel Nova resource (Reviews) data using 2 'select-filters'.

I have a filter A = Manufacturers and filter B = Models.

A Manufacturer has many Models. I have manufacturer and model column in products table.

'Model' filter by default show all the values in the select dropdown. I want to reduce the select options in the 'Model' filter when 'Manufacturer' is selected.

so, for example: When Manufacturer = "Apple" then 'Model' filter should show only Apple 'Models'.

In my Review Resource, I have below code:

/**
 * Get the filters available for the resource.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return array
 */
public function filters(Request $request)
{
    return [
        new Manufacturer(),
        new Model(),
    ];
}

Manufacturer Filter code

class Manufacturer extends Filter
{
    
    /**
     * The filter's component.
     *
     * @var string
     */
    public $component = 'select-filter';

/**
 * Apply the filter to the given query.
 *
 * @param \Illuminate\Http\Request              $request
 * @param \Illuminate\Database\Eloquent\Builder $query
 * @param mixed                                 $value
 *
 * @return \Illuminate\Database\Eloquent\Builder
 */
public function apply(Request $request, $query, $value)
{
    return $query->whereHas('product', function ($query) use ($value) {
        $query->where('manufacturer', $value);
    });
}

/**
 * Get the filter's available options.
 *
 * @param \Illuminate\Http\Request $request
 *
 * @return array
 */
public function options(Request $request)
{
    return Product::select('manufacturer')
        ->withoutGlobalScopes()
        ->withoutTrashed()
        ->groupBy('manufacturer')
        ->orderBy('manufacturer')
        ->pluck('manufacturer')
        ->mapWithKeys(function ($manufacturer) {
            return [$manufacturer => strtolower($manufacturer)];
        })
        ->toArray();
}

}

Model Filter code

class Model extends Filter
{
    
    /**
     * The filter's component.
     *
     * @var string
     */
    public $component = 'select-filter';

/**
 * Apply the filter to the given query.
 *
 * @param \Illuminate\Http\Request              $request
 * @param \Illuminate\Database\Eloquent\Builder $query
 * @param mixed                                 $value
 *
 * @return \Illuminate\Database\Eloquent\Builder
 */
public function apply(Request $request, $query, $value)
{
    return $query->whereHas('product', function ($query) use ($value) {
        $query->where('model', $value);
    });
}

/**
 * Get the filter's available options.
 *
 * @param \Illuminate\Http\Request $request
 *
 * @return array
 */
public function options(Request $request)
{
    //
    //
    //I want to add a condition below ->where('manufacturer', $manufacturer)
    //
    //

    return Product::select('model')
        ->withoutGlobalScopes()
        ->withoutTrashed()
        ->groupBy('model')
        ->orderBy('model')
        ->pluck('model')
        ->mapWithKeys(function ($model) {
            return [$model => strtolower($model)];
        })
        ->toArray();
}

}

I tried to decode $request to get the filter values but returns null.

1 Answers

I found the library that helps achieve exactly what I wanted.

The library can be found here: https://github.com/awesome-nova/dependent-filter

Once the above library is installed, the two filters can be set as shown below:

Filter A

<?php

namespace App\Nova\Filters;

use Illuminate\Http\Request;
use App\Models\Product;
use AwesomeNova\Filters\DependentFilter;

class Manufacturer extends DependentFilter
{
/**
 * Name of filter.
 *
 * @var string
 */
public $name = 'Manufacturer';

/**
 * Attribute name of filter. Also it is key of filter.
 *
 * @var string
 */
public $attribute = 'manufacturer';

/**
 * The filter's component.
 *
 * @var string
 */
public $component = 'awesome-nova-dependent-filter';

/**
 * Apply the filter to the given query.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \Illuminate\Database\Eloquent\Builder  $query
 * @param  mixed  $value
 * @return \Illuminate\Database\Eloquent\Builder
 */
public function apply(Request $request, $query, $value)
{
    return $query->whereHas('product', function ($query) use ($value) {
        $query->where('manufacturer', $value);
    });
}

/**
 * Get the filter's available options.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return array
 */
public function options(Request $request, array $filters = [])
{
    return Product::select('manufacturer')
        ->pluck('manufacturer')
        ->mapWithKeys(function ($manufacturer) {
            return [$manufacturer => $manufacturer];
        })->toArray();
}

Filter B

<?php

namespace App\Nova\Filters;

use App\Models\Product;
use Illuminate\Http\Request;
use AwesomeNova\Filters\DependentFilter;

class Model extends DependentFilter
{
    /**
     * Name of filter.
     *
     * @var string
     */
    public $name = 'Model';
    
    /**
     * Attribute name of filter. Also it is key of filter.
     *
     * @var string
     */
    public $attribute = 'model';
    
    /**
     * The filter's component.
     *
     * @var string
     */
    public $component = 'awesome-nova-dependent-filter';

    /**
     * The filter's dependentOf.
     *
     * @var array
     */
    public $dependentOf = ['manufacturer'];

    public $hideWhenEmpty = true;

    /**
     * Apply the filter to the given query.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Illuminate\Database\Eloquent\Builder  $query
     * @param  mixed  $value
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function apply(Request $request, $query, $value)
    {
        return $query->whereHas('product', function ($query) use ($value) {
            $query->where('model', $value);
        });
    }

    /**
     * Get the filter's available options.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    public function options(Request $request, array $filters = [])
    {
        return Product::select('model')
            ->where('manufacturer', $filters['manufacturer'])
            ->pluck('model')
            ->mapWithKeys(function ($model) {
                return [$model => $model];
            })->toArray();
    }
}

Resource File

public function filters(Request $request)
{
    return [
        Manufacturer::make(),
        Model::make(),
    ];
}
Related