Dmytro
Dmytro
FFilament
Created by Dmytro on 5/6/2025 in #❓┊help
Is there a way to stop the reordering of options for Select?
I need a Select component which allows select multiple options and store the order of selected option, in my example I have Dish and Ingredient models, Dish has belongsToMany relation to ingredients. Pivot table dish_ingredient has additional order column. Select component configured like this
Select::make('ingredients')
->multiple()
->relationship('ingredients', 'name')
->required()
->searchDebounce(500)
->saveRelationshipsUsing(function (Dish $record, $state) {
$record->ingredients()->sync(
collect($state)
->mapWithKeys(function ($id, $index) {
return [$id => ['order' => $index + 1]];
})
->all()
);
})
->columnSpanFull(),
Select::make('ingredients')
->multiple()
->relationship('ingredients', 'name')
->required()
->searchDebounce(500)
->saveRelationshipsUsing(function (Dish $record, $state) {
$record->ingredients()->sync(
collect($state)
->mapWithKeys(function ($id, $index) {
return [$id => ['order' => $index + 1]];
})
->all()
);
})
->columnSpanFull(),
To keep initial ordering I added orderByPivot.
public function ingredients(): BelongsToMany
{
return $this->belongsToMany(Ingredient::class)
->orderByPivot('order');
}
public function ingredients(): BelongsToMany
{
return $this->belongsToMany(Ingredient::class)
->orderByPivot('order');
}
I fixed ordering after adding a new option using getOptionLabelsUsing callback:
->getOptionLabelsUsing(
function (Select $component, array $values) {
/** @var Collection $existingOptions */
$existingOptions = $component->getRecord()->ingredients()->whereIn('id', $values)->pluck('name', 'id');

$optionIdsToAttach = array_diff($values, $existingOptions->keys()->toArray());
$optionsToAttach = Ingredient::query()->whereIn('id', $optionIdsToAttach)->pluck('name', 'id');

return $existingOptions->union($optionsToAttach)->toArray();
}
)
->getOptionLabelsUsing(
function (Select $component, array $values) {
/** @var Collection $existingOptions */
$existingOptions = $component->getRecord()->ingredients()->whereIn('id', $values)->pluck('name', 'id');

$optionIdsToAttach = array_diff($values, $existingOptions->keys()->toArray());
$optionsToAttach = Ingredient::query()->whereIn('id', $optionIdsToAttach)->pluck('name', 'id');

return $existingOptions->union($optionsToAttach)->toArray();
}
)
The problem is that options are reordered on the UI during searching or after adding a new option. I need stop this. Looks like the order is changed by JS and i have no idea how to stop this.
1 replies