Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Nova Sortable 5 Laravel Package

almirhodzic/nova-sortable-5

A Laravel Nova 5 package that adds drag-and-drop sorting to resource index tables. Reorder rows directly in Nova, persist positions through a configurable sort column, and keep listings organized with minimal setup. Ideal for menus, categories, FAQs, and other ordered content.

View on GitHub
Deep Wiki
Context7

Getting Started

  • Install the package with Composer. Confirm the dependency constraint targets Nova 5: v1.0.4 implements Nova 5's Resource::indexQuery() contract. Projects still on Nova 4 should pin the last pre-1.0.4 release rather than mixing versions.
  • Add an order column to the resource's table (typically an indexed integer, nullable during backfill). Backfill existing rows before enabling drag-and-drop so sorting is deterministic.
  • Register the field in the Nova Resource's fields() method:
use Vendor\NovaSortable\Sortable;

public function fields(NovaRequest $request)
{
    return [
        Sortable::make('Order', 'order'),
        // other fields...
    ];
}
  • Ensure the index is ordered by the column. With Nova 5, override indexQuery() using the contract signature:
use Illuminate\Database\Eloquent\Builder;
use Laravel\Nova\Http\Requests\NovaRequest;

public static function indexQuery(NovaRequest $request, $query): Builder
{
    return parent::indexQuery($request, $query)->orderBy('order');
}
  • First use case: open the resource index, drag a row, refresh, and confirm the new order persists. Then verify the field is absent from create/update forms and present on index/detail.
  • Look first at: the Resource's fields() method, the model's order column, the Resource's indexQuery(), and the package's published FormSortable.vue if you need to customize the front-end behavior.

Implementation Patterns

  • Standard resource integration. Add the field unconditionally in fields(); v1.0.4 hides it on create/update forms itself. Rely on that instead of manually adding showOnCreating() / showOnUpdating(), which would reintroduce the form-binding bug.
  • Global ordering. For a simple sortable list, set order on create (Model::max('order') + 1) and resequence after deletes. Use a model observer or a small Artisan command so gaps do not accumulate.
  • Scoped ordering. For team-, tenant-, or category-scoped resources, scope both the indexQuery() ordering and the reorder write. A common pattern is ordering by (scope_id, order) and resequencing within the same scope when a row moves.
  • Quiet writes. Persist reordered values with updateQuietly() / saveQuietly() or a direct query builder update, otherwise model observers that assign order values can fire recursively.
  • Custom Vue components. If you extend or publish FormSortable.vue, use the Options API and Nova's DependentFormField mixin. Do not use <script setup>; Nova expects the component to expose fill() on the field data object.
  • Authorization. The drag-and-drop endpoint should respect the resource policy's update ability. Verify the package's route middleware and field-level canSee/canUpdate behavior before exposing reordering to non-admin users.
  • Testing. Write a feature test that posts the reorder payload through Nova's request stack, then asserts the order column values. Also cover the indexQuery() ordering and the field's visibility rules.
  • Bulk workflows. If you need “move to top/bottom” or bulk reorder actions, implement them as Nova actions that update the order column and resequence in a transaction rather than relying only on drag-and-drop.

Gotchas and Tips

  • t.fill is not a function on form submit. This was the pre-1.0.4 failure mode caused by <script setup> not exposing the fill() method Nova binds through DependentFormField. v1.0.4 fixes it by switching to the Options API. If you published the Vue component, re-publish or diff it after upgrading; stale published views or compiled assets will keep the old behavior. Rebuild assets and clear caches.
  • Nova 5 indexQuery signature drift. Any Resource override must use the Nova 5 signature with the Builder type-hint and return type. Copying an older signature causes type errors on the index endpoint.
public static function indexQuery(NovaRequest $request, $query): Builder
  • Do not force the field onto forms. The field is intentionally index/detail-only. If you need to display the value on detail, use a read-only field there; do not make the sortable field editable on create/update.
  • Filtered or searched lists break naive drag-and-drop. Reordering a filtered subset only renumbers visible rows and can collide with hidden rows. Either disable drag-and-drop while filters are active, scope order to the filtered dimension, or resequence the whole set after each move.
  • Concurrent drags can duplicate order values. Wrap reorder writes in a transaction and normalize periodically. Avoid a hard unique index on order unless your update strategy updates rows in a collision-safe order (for example, temporary negative values before resequencing).
  • Null order values sort inconsistently. MySQL and PostgreSQL treat NULL ordering differently. Backfill before enabling the field; keep the column non-nullable once migration is complete.
  • Stale assets are a common source of “fixed” bugs. After upgrading, run php artisan optimize:clear, republish any package views/assets, and rebuild Nova custom assets. Browser console errors often come from old compiled JavaScript rather than PHP.
  • Debugging reorder failures. Inspect the network request payload for the drag-and-drop endpoint, check storage/logs/laravel.log, and confirm the resource policy allows updates. If the order saves but the index does not reflect it, check indexQuery() ordering and any global scopes on the model.
  • Extension points. Publish and override the Vue field component if you need custom drag behavior, and use the DependentFormField mixin pattern for any Nova form-field interoperability. Keep customizations in a local component rather than editing vendor files so future releases remain upgradeable.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core
nodisrupt/laravel-agent
sierratecnologia/media-manager