1

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 Answer 1

0

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(),
    ];
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.