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'))