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

Laravel Livewire Tables Laravel Package

caseraph/laravel-livewire-tables

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require caseraph/laravel-livewire-tables
    

    Publish the config (if needed):

    php artisan vendor:publish --provider="Caseraph\LivewireTables\LivewireTablesServiceProvider"
    
  2. First Component Create a Livewire component:

    php artisan make:livewire Admin/UsersTable
    

    Update the component class (app/Http/Livewire/Admin/UsersTable.php):

    use Caseraph\LivewireTables\LivewireTable;
    
    class UsersTable extends LivewireTable
    {
        public function configure(): void
        {
            $this->setPrimaryKey('id');
            $this->setSearch(['name', 'email']);
            $this->setPerPage(10);
        }
    
        public function columns(): array
        {
            return [
                'name' => 'Name',
                'email' => 'Email',
                'created_at' => 'Created At',
            ];
        }
    
        public function query(): Builder
        {
            return User::query();
        }
    }
    
  3. First Blade View

    <livewire:admin.users-table />
    

Key First Use Case

Replace a static Eloquent paginate() table with dynamic filtering, sorting, and pagination in under 10 minutes. Example:

// Replace this:
public function render()
{
    return view('livewire.users', [
        'users' => User::paginate(10),
    ]);
}

// With this:
public function render()
{
    return view('livewire.users');
}

Implementation Patterns

Core Workflow

  1. Define Data Source Override query() to return a base Eloquent query:

    public function query(): Builder
    {
        return User::with('roles')->where('active', true);
    }
    
  2. Configure Table Behavior

    public function configure(): void
    {
        $this->setPrimaryKey('id');
        $this->setSearch(['name', 'email', 'phone']);
        $this->setPerPage(25);
        $this->setDefaultSort('name', 'asc');
        $this->setSearchDebounce(500); // ms
    }
    
  3. Customize Columns

    public function columns(): array
    {
        return [
            'name' => Column::make('Name')
                ->sortable()
                ->searchable(),
            'email' => Column::make('Email')
                ->toggleable(isToggledByDefault: true),
            'roles' => Column::make('Roles')
                ->format(fn ($value, $row) => $row->roles->pluck('name')->join(', ')),
            'actions' => Column::make('Actions')
                ->view('livewire-tables::columns.actions', [
                    'edit' => route('users.edit', $row->id),
                    'delete' => route('users.destroy', $row->id),
                ]),
        ];
    }
    
  4. Add Actions

    public function actions(): array
    {
        return [
            'edit' => Action::make('Edit')
                ->icon('edit')
                ->url(fn ($row) => route('users.edit', $row->id)),
            'delete' => Action::make('Delete')
                ->icon('trash')
                ->action(fn ($row) => $this->deleteUser($row)),
        ];
    }
    
    public function deleteUser(User $user): void
    {
        $user->delete();
        $this->dispatch('user-deleted');
    }
    

Integration Tips

  • API Integration: Use setApiEndpoint() to fetch data from a custom API:
    public function configure(): void
    {
        $this->setApiEndpoint('/api/users');
    }
    
  • Nested Relationships: Eager load and access nested data:
    public function query(): Builder
    {
        return User::with('department.projects');
    }
    
    public function columns(): array
    {
        return [
            'department.projects' => Column::make('Projects')
                ->format(fn ($value) => $value->pluck('name')->join(', ')),
        ];
    }
    
  • Conditional Logic: Use canSee() to hide/show columns/actions:
    public function columns(): array
    {
        return [
            'email' => Column::make('Email')
                ->canSee(fn () => auth()->user()->isAdmin()),
        ];
    }
    

Gotchas and Tips

Common Pitfalls

  1. Performance Issues

    • Problem: Slow queries due to missing with() or unoptimized where clauses.
    • Fix: Always eager-load relationships and add indexes to frequently filtered columns.
    • Tip: Use setQueryCallback() for complex queries that can't be built incrementally:
      public function configure(): void
      {
          $this->setQueryCallback(fn () => $this->buildComplexQuery());
      }
      
  2. Search Not Working

    • Problem: Search ignores certain columns or returns no results.
    • Fix: Ensure columns are marked as searchable() and that the search fields are included in setSearch().
    • Debug: Check the generated SQL by temporarily adding ->toSql() to your query.
  3. Pagination Conflicts

    • Problem: Pagination breaks when using custom query scopes.
    • Fix: Ensure your base query returns a Builder instance, not a collection or array:
      // Wrong:
      return User::active()->get();
      
      // Right:
      return User::active()->query();
      
  4. Livewire State Persistence

    • Problem: Table state (sorting, pagination) resets on page refresh.
    • Fix: Use setPersistState(true) in configure() to save state in session:
      public function configure(): void
      {
          $this->setPersistState(true);
      }
      

Debugging Tips

  • Log Queries: Add this to your configure() to log generated queries:

    public function configure(): void
    {
        $this->setQueryLogger(true);
    }
    

    Check logs in storage/logs/laravel-livewire-tables.log.

  • Inspect State: Dump the current table state for debugging:

    dd($this->getState());
    
  • Disable JavaScript: Test your table with JS disabled to ensure server-side rendering works:

    public function configure(): void
    {
        $this->setDisableClientSide(true);
    }
    

Extension Points

  1. Custom Views Override default views by publishing assets:

    php artisan vendor:publish --tag=livewire-tables-views
    

    Then modify resources/views/vendor/livewire-tables/.

  2. Custom Styling Use Tailwind/Blade classes or override the default CSS:

    <livewire:admin.users-table :class="'bg-gray-100'" />
    
  3. Event Handling Listen for table events (e.g., row selection, bulk actions):

    protected $listeners = ['rowSelected' => 'handleRowSelection'];
    
    public function handleRowSelection($rowId)
    {
        $this->selectedRows[] = $rowId;
    }
    
  4. Bulk Actions Implement bulk actions with setBulkActions():

    public function configure(): void
    {
        $this->setBulkActions([
            'delete' => Action::make('Delete Selected')
                ->action(fn () => $this->deleteSelected()),
        ]);
    }
    
    public function deleteSelected(): void
    {
        $this->query()->whereIn('id', $this->getSelectedRows())->delete();
        $this->dispatch('bulk-action-completed');
    }
    

Pro Tips

  • Reusable Components: Create a base table component for shared functionality:

    class BaseTable extends LivewireTable
    {
        public function configure(): void
        {
            $this->setPerPage(20);
            $this->setSearchDebounce(300);
            $this->setEmptyState('No records found.');
        }
    }
    

    Extend it in child components:

    class UsersTable extends BaseTable { ... }
    
  • Dynamic Columns: Load columns dynamically based on user roles:

    public function columns(): array
    {
        $columns = ['name', 'email'];
        if (auth()->user()->isAdmin()) {
            $columns[] = 'deleted_at';
        }
        return array_map(fn ($col) => Column::make($col), $columns);
    }
    
  • Export Functionality: Add CSV/Excel export with a single action:

    public function actions(): array
    {
        return [
            'export' => Action::make('Export')
                ->icon('download')
                ->action(fn () => $this->export()),
        ];
    }
    
    public function export(): void
    {
        $
    
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.
codraw/framework-extra-bundle
codraw/messenger
codraw/security
codraw/mailer
codraw/contracts
codraw/profiling
codraw/dependency-injection
codraw/tester
codraw/core
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