Home > Blockchain >  Laravel filament multiselect from the comma separated list
Laravel filament multiselect from the comma separated list

Time:09-12

I am trying to implement filament admin panel for a existing project. I would like to implement multiselect. Table structure is as below:

Products

id name categories
1 product-1 1, 2, 4
2 product-2 1, 2
3 product-3 2, 4
4 product-4 4

Categories

id name
1 cat-1
2 cat-2
3 cat-3
4 cat-4

What I tried so far

Option 1

I tried to use getter/setter in product model like:

public function getcategoriesAttribute()
{
    $categoriesId = $this->getRawOriginal('categories');

    return Category::whereIn('id', explode(',', $categoriesId))
        ->get()
        ->pluck('id', 'categories');
}

public function setcategoriesAttribute($ids)
{
    $this->attributes['name'] = is_string($ids) ? $ids : implode(',', $ids);
}

And in resource file:

...
MultiSelect::make('categories')
...

Using this solution I am able to list categories correctly but multiselect is not able to either show select nor show list of categories.

Option 2

In this solution I tried to use filament relationship for fields without getter/setter like below:

MultiSelect::make('categories')
    ->relationship('categories', 'id')
    ->options(fn ($record) => Category::get()->pluck('name', 'id'))

This solution is able to list all categories in multiselect dropdown but is not able to show list of already selected categories either in multiselect dropdown nor on index page/table.

Solution I am looking for

I would like to list categories as tags in table and also would like to use multi-select while editing the product.

Solution

For Laravel 9: Follow answer by Dan Harrin

For Laravel 8: Use traditional way of get/set in the model.

public function getCategoriesAttribute($value)
{
    return explode(',', $value);
}

public function setCategoriesAttribute($value)
{
    $this->attributes['categories'] = implode(',', $value);
}

CodePudding user response:

Firstly, you should update the getter and setter so they only explode and implode the comma separated string into an array:

use Illuminate\Database\Eloquent\Casts\Attribute;

protected function categories(): Attribute
{
    return Attribute::make(
        get: fn ($value) => explode(',', $value),
        set: fn ($value) => implode(',', $value),
    );
}

Then you should just be able to use the multiselect like normal:

MultiSelect::make('categories')
    ->options(Category::pluck('name', 'id'))
  • Related