Такой способ сортировки подходит только если записей мало и не используется пагинация!
В данном примере таблица ресурса будет сортироваться по полю position, поэтому убедитесь, что это поле есть у модели.
Добавьте в свой ресурс следующий код:
use MoonShine\Contracts\UI\ComponentContract;use MoonShine\Contracts\Core\DependencyInjection\CrudRequestContract;use MoonShine\UI\Components\Table\TableBuilder;protected string $sortColumn = 'position';protected SortDirection $sortDirection = SortDirection::ASC;/*** @param TableBuilder $component*/public function modifyListComponent(ComponentContract $component): ComponentContract{return $component->reorderable($this->getAsyncMethodUrl('reorder'));}public function reorder(CrudRequestContract $request): void{if ($request->str('data')->isNotEmpty()) {$request->str('data')->explode(',')->each(fn($id, $position) => $this->getModel()->where('id', $id)->update(['position' => $position + 1,]),);}}use MoonShine\Contracts\UI\ComponentContract;use MoonShine\Contracts\Core\DependencyInjection\CrudRequestContract;use MoonShine\UI\Components\Table\TableBuilder;protected string $sortColumn = 'position';protected SortDirection $sortDirection = SortDirection::ASC;/*** @param TableBuilder $component*/public function modifyListComponent(ComponentContract $component): ComponentContract{return $component->reorderable($this->getAsyncMethodUrl('reorder'));}public function reorder(CrudRequestContract $request): void{if ($request->str('data')->isNotEmpty()) {$request->str('data')->explode(',')->each(fn($id, $position) => $this->getModel()->where('id', $id)->update(['position' => $position + 1,]),);}}
При таком подходе можно перетаскивать строки хватаясь курсором за любую ячейку. Чтобы аккуратно перетаскивать строки за ручку (как сделано в поле Json), необходимо добавить колонку-ручку с заданным классом и передать этот класс библиотеке SortableJS. Содержимое колонки не важно — в данном примере ставится иконка, а класс handle добавляется всей ячейке.
Добавьте новое поле в метод fields() индексной страницы с иконкой ручки:
protected function fields(): iterable{return [Preview::make(column: '__handle',formatted: static fn () => Icon::make('bars-4'),)->customWrapperAttributes(['class' => 'handle', 'style' => 'cursor: move']),// ... Прочие колонки таблицы];}protected function fields(): iterable{return [Preview::make(column: '__handle',formatted: static fn () => Icon::make('bars-4'),)->customWrapperAttributes(['class' => 'handle', 'style' => 'cursor: move']),// ... Прочие колонки таблицы];}
Чтобы сообщить SortableJS какой элемент будет ручкой, следует добавить таблице атрибут data-handle с css селектором. В данном примере это класс handle. Дополните метод ресурса:
public function modifyListComponent(ComponentContract $component): ComponentContract{return $component->reorderable($this->getAsyncMethodUrl('reorder'))->customAttributes(['data-handle' => '.handle',]);}public function modifyListComponent(ComponentContract $component): ComponentContract{return $component->reorderable($this->getAsyncMethodUrl('reorder'))->customAttributes(['data-handle' => '.handle',]);}
Теперь строки перетаскиваются только за первую ячейку, оставляя прочие столбцы свободными для взаимодействия и выделения текста.
Также можно не добавлять отдельную ячейку-ручку, а добавить класс уже существующему столбцу и передать селектор в data-handle.