Weave Code
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

Filament Record Nav Laravel Package

nben/filament-record-nav

View on GitHub
Deep Wiki
Context7

Getting Started

Install via Composer:

composer require nben/filament-record-nav

First use case: Add navigation to a ViewRecord or EditRecord page by including these two lines in getHeaderActions():

use Nben\FilamentRecordNav\Actions\{NextRecordAction, PreviousRecordAction};

protected function getHeaderActions(): array
{
    return [
        PreviousRecordAction::make(),
        NextRecordAction::make(),
    ];
}

Where to look first:

  1. README Quick Start for basic usage
  2. Configuration for order_column settings
  3. Demo to see the UI behavior

Implementation Patterns

Core Workflow

  1. Default Integration (90% of cases):

    // ViewPost.php
    protected function getHeaderActions(): array
    {
        return [
            PreviousRecordAction::make()
                ->label('← Previous')
                ->color('gray')
                ->size(Size::Small),
            NextRecordAction::make()
                ->label('Next →')
                ->color('gray')
                ->size(Size::Small),
        ];
    }
    
  2. Page-Type Control:

    // Navigate previous to view, next to edit
    PreviousRecordAction::make()->navigateTo(NavigationPage::View),
    NextRecordAction::make()->navigateTo(NavigationPage::Edit),
    
  3. Custom Route Handling:

    // In resource:
    public static function getPages(): array { return ['custom-view' => ...]; }
    
    // In page:
    PreviousRecordAction::make()
        ->navigateTo(NavigationPage::custom('custom-view'))
        ->label('View Alternate'),
    

Integration Tips

  • Resource-wide consistency: Use the same order_column across all resources for predictable navigation
  • Button styling: Apply consistent sizing/colors via ->size()/->color() to match your admin theme
  • Keyboard shortcuts: Add ->keyBindings() for power users:
    PreviousRecordAction::make()->keyBindings(['mod+left'])
    

Advanced Patterns

  1. Scoped Navigation (using the trait):

    use Nben\FilamentRecordNav\Concerns\WithRecordNavigation;
    
    class ViewPost extends ViewRecord
    {
        use WithRecordNavigation;
    
        public function getPreviousRecord(): ?Model
        {
            return $this->getRecord()
                ->newQuery()
                ->where('status', 'published')
                ->where('published_at', '<', $this->getRecord()->published_at)
                ->orderBy('published_at', 'desc')
                ->first();
        }
    }
    
  2. Dynamic URL Resolution:

    public function getRecordNavigationUrl(Model $record, $page): string
    {
        return match($page->value) {
            'view' => $record->is_verified
                ? static::getResource()::getUrl('verified-view', ['record' => $record])
                : static::getResource()::getUrl('view', ['record' => $record]),
            default => static::getResource()::getUrl($page->value, ['record' => $record]),
        };
    }
    

Gotchas and Tips

Common Pitfalls

  1. Disabled Buttons:

    • Cause: Duplicate order_column values (e.g., identical timestamps)
    • Fix: Add ->orderBy('id') to queries in custom navigation methods
  2. Route Not Found:

    • Cause: Mismatched route names in NavigationPage::custom()
    • Fix: Verify getPages() keys match exactly (including hyphens/casing)
  3. Performance Issues:

    • Cause: Missing database index on order_column
    • Fix: Add index via migration:
      Schema::table('posts', function (Blueprint $table) {
          $table->index('order_column');
      });
      

Debugging Tips

  • Verify Queries: Temporarily add:

    public function getPreviousRecord(): ?Model
    {
        \Log::info('Query:', [
            'record_id' => $this->getRecord()->id,
            'query' => $this->getRecord()->newQuery()->toSql()
        ]);
        return $this->getRecord()->newQuery()->where('id', '<', $this->getRecord()->id)->first();
    }
    
  • Check Cache: The package caches results per render. Clear cache if testing changes:

    // In your test page
    protected function resolveRecordNavigationCache(): void
    {
        $this->resolvedRecordCache = [];
    }
    

Configuration Quirks

  1. Timestamp Columns:

    • Use created_at/updated_at only if all records have unique values
    • For identical timestamps, add secondary sorting:
      // config/filament-record-nav.php
      'order_column' => ['created_at', 'id'],
      
  2. Custom Ordering:

    • For complex ordering (e.g., CASE WHEN...), override both methods:
      public function getPreviousRecord(): ?Model
      {
          return $this->getRecord()
              ->newQuery()
              ->whereRaw('
                  CASE
                      WHEN status = "draft" THEN 0
                      WHEN status = "published" THEN 1
                  END < ?
              ', [$this->getRecord()->getStatusValue()])
              ->orderByRaw('
                  CASE
                      WHEN status = "draft" THEN 0
                      WHEN status = "published" THEN 1
                  END DESC
              ')
              ->first();
      }
      

Extension Points

  1. Dynamic Button Visibility:

    PreviousRecordAction::make()
        ->visible(fn () => auth()->user()->can('view_archived') || !$this->record->is_archived),
    
  2. Custom Icons:

    PreviousRecordAction::make()
        ->icon(fn () => $this->record->is_first ? 'heroicon-o-chevron-left' : 'heroicon-o-arrow-path')
        ->color(fn () => $this->record->is_first ? 'gray' : 'primary'),
    
  3. Event-Based Navigation:

    // In your page
    protected static function getNavigationEvents(): array
    {
        return [
            'record-navigated' => fn (Model $record) => event(new RecordNavigated($record)),
        ];
    }
    

Performance Optimization

  • Indexing: Always index your order_column (or composite columns)
  • Query Scoping: For large tables, scope queries in custom methods:
    public function getNextRecord(): ?Model
    {
        return $this->getRecord()
            ->newQuery()
            ->where('tenant_id', $this->getRecord()->tenant_id)
            ->where('status', 'published')
            ->where('published_at', '>', $this->getRecord()->published_at)
            ->orderBy('published_at')
            ->first();
    }
    

Type Safety

For IDE support when using the trait:

use Nben\FilamentRecordNav\Concerns\WithRecordNavigation;
use Nben\FilamentRecordNav\Contracts\HasRecordNavigation;

class ViewPost extends ViewRecord implements HasRecordNavigation
{
    use WithRecordNavigation;
}
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.
nexmo/api-specification
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
ecotone/kafka
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata