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

alp-develop/laravel-livewire-tables

Reactive Livewire data tables for Laravel—search, sort, filter, paginate, export, and bulk actions with zero JavaScript. Supports Laravel 10–13, Livewire 3–4, PHP 8.1+, Tailwind or Bootstrap 4/5, plus dark mode and configurable themes.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require alp-develop/laravel-livewire-tables
    php artisan vendor:publish --tag=livewire-tables-config
    

    Configure config/livewire-tables.php (set theme to tailwind, bootstrap-5, or bootstrap-4).

  2. Generate a Table:

    php artisan make:livewiretable UsersTable User
    

    This creates a scaffolded UsersTable class in app/Livewire/Tables/.

  3. First Use Case:

    • Edit the generated UsersTable to define columns, filters, and actions (see Quick Start in README).
    • Render the table in a Blade view:
      <livewire:tables.users-table />
      

Where to Look First

  • Columns: docs/columns.md (e.g., TextColumn, BooleanColumn, ActionColumn).
  • Filters: docs/filters.md (e.g., SelectFilter, DateFilter).
  • Configuration: config/livewire-tables.php (themes, dark mode, defaults).
  • Quick Start Example: The UsersTable example in the README covers 90% of use cases.

Implementation Patterns

Core Workflow

  1. Define the Table Class: Extend Livewire\Tables\Livewire\DataTableComponent and implement:

    • query(): Return the base Eloquent query.
    • columns(): Define columns (e.g., TextColumn::make('name')->sortable()).
    • filters(): Add filters (e.g., SelectFilter::make('status')).
    • bulkActions(): Register actions (e.g., deleteSelected, exportCsvAuto).
    • configure(): Set defaults (e.g., setDefaultPerPage(25)).
  2. Render the Table: Use <livewire:tables.users-table /> in Blade. For multiple instances, pass a unique table-key:

    <livewire:tables.users-table table-key="active-users" />
    
  3. Handle Actions: Implement methods for bulk/actions (e.g., deleteSelected(), edit(int $id)). Use $this->getSelectedIds() for bulk operations.

Integration Tips

  • Dynamic Data: Pass dynamic data via Livewire properties:

    <livewire:tables.users-table :user-role="$role" />
    

    Access in the component with public $userRole.

  • Conditional Columns: Use isVisible() in columns:

    TextColumn::make('email')->visible(fn ($row) => $row->isAdmin()),
    
  • Custom Queries: Override query() to scope data:

    public function query(): Builder
    {
        return User::where('department', $this->department)->query();
    }
    
  • Toolbar Slots: Add custom content to the toolbar using slots:

    <livewire:tables.users-table>
        <x-slot name="toolbar-right">
            <button wire:click="customAction">Custom Button</button>
        </x-slot>
    </livewire:tables.users-table>
    
  • Dark Mode: Enable in config and toggle via JavaScript:

    document.documentElement.classList.toggle('lt-dark');
    window.dispatchEvent(new Event('lt-dark-toggled'));
    

    Store session value (e.g., session(['lt-dark' => true])).

  • Export Customization: Override exportCsvAuto() or use export() for custom exports:

    public function export(): void
    {
        $this->exportCsv('users_export', function ($query) {
            return $query->select('name', 'email');
        });
    }
    
  • Joins: Use query() to add joins, then reference joined columns in columns():

    public function query(): Builder
    {
        return User::query()->join('roles', 'users.role_id', 'roles.id');
    }
    // In columns:
    TextColumn::make('roles.name')->label('Role'),
    
  • Events: Listen for table events (e.g., table.rendered) to trigger side effects:

    public function boot()
    {
        $this->dispatchBrowserEvent('table-rendered');
    }
    

Gotchas and Tips

Pitfalls

  1. Shared State Without table-key:

    • Issue: Multiple instances of the same table component share state (filters, search, sort) if no table-key is set.
    • Fix: Always pass a unique table-key for multiple instances:
      <livewire:tables.users-table table-key="users-active" />
      
  2. Column Field Mismatches:

    • Issue: If the field() in a column doesn’t match the query results, the column may render blank or throw errors.
    • Fix: Ensure field() matches the database column or use format() to transform values:
      TextColumn::make('created_at')->format(fn ($value) => $value->format('M d, Y')),
      
  3. Filter Value Normalization:

    • Issue: Filters may not work as expected if values aren’t normalized (e.g., string vs. integer).
    • Fix: Implement normalizeValue() in custom filters or ensure filter values match the query:
      SelectFilter::make('status')
          ->setOptions(['active' => 'Active', 'inactive' => 'Inactive'])
          ->filter(fn (Builder $q, $v) => $q->where('status', $v)),
      
  4. Bulk Actions and Selected IDs:

    • Issue: $this->getSelectedIds() may return unexpected results if rows are deleted/reordered between selections.
    • Fix: Use getSelectedIds() immediately before the bulk action and handle edge cases:
      public function deleteSelected(): void
      {
          $ids = $this->getSelectedIds();
          if (empty($ids)) return;
          User::whereIn('id', $ids)->delete();
      }
      
  5. Dark Mode Not Applying:

    • Issue: Dark mode styles don’t update or $this->darkMode is always false.
    • Fix:
      • Ensure dark_mode.enabled is true in config.
      • Verify the session key (selector) matches the stored value.
      • Dispatch the lt-dark-toggled event after toggling the CSS class.
  6. Performance with Large Datasets:

    • Issue: Slow rendering or timeouts with large datasets due to eager loading or complex queries.
    • Fix:
      • Use with() sparingly in query().
      • Add indexes to frequently filtered/sorted columns.
      • Limit columns in columns() to only those needed.
  7. Custom Steps Not Triggering:

    • Issue: Custom pipeline steps (e.g., SoftDeleteStep) aren’t applied.
    • Fix:
      • Ensure the step is added to the Engine in getEngine() or via configure().
      • Cache the Engine instance in $this->cachedEngine:
        protected function getEngine(): Engine
        {
            if ($this->cachedEngine) return $this->cachedEngine;
            return $this->cachedEngine = (new Engine($columns, $filters))
                ->addStep(new SoftDeleteStep);
        }
        
  8. Export Formulas Vulnerability:

    • Issue: CSV exports may expose sensitive data if formulas are injected.
    • Fix: Use export() with a closure to control output:
      public function export(): void
      {
          $this->exportCsv('safe_export', function ($query) {
              return $query->select('name', 'email')->addSelect(\DB::raw('CONCAT(first_name, " ", last_name) as full_name'));
          });
      }
      

Debugging Tips

  1. Log the Query: Use toSql() and getBindings() to debug the generated query:

    public function query(): Builder
    {
        $query = User::query();
        \Log::info($query->toSql(), $query->getBindings());
        return $query;
    }
    
  2. Inspect State: Dump the State object to verify search, filters, and sort values:

    public function mount()
    {
        \Log::info($this->state);
    }
    
  3. Check Engine Steps: Log the pipeline steps to ensure custom steps are applied:

    protected function getEngine(): Engine
    {
        $engine = (new Engine($columns, $filters))
            ->addStep(new \App\Steps\SoftDeleteStep);
        \Log::info('Engine steps:', $engine->steps());
        return $this->cachedEngine = $engine;
    }
    
  4. Verify Table Key: Check if table-key is being passed correctly:

    public function mount($tableKey
    
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/entity-migrator
codraw/doctrine-extra
codraw/aws-tool-kit
codraw/validator
codraw/workflow
codraw/open-api
codraw/cron-job
codraw/process
codraw/log
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