FilamentF
Filament8mo ago
Dmytro

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(),

To keep initial ordering I added orderByPivot.
  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();
    }
)

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.
Was this page helpful?