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

Livewire Datatables Laravel Package

mediconesystems/livewire-datatables

View on GitHub
Deep Wiki
Context7
## Getting Started

### Minimal Setup
1. **Installation**:
   ```bash
   composer require mediconesystems/livewire-datatables

Publish the config and migrations:

php artisan vendor:publish --provider="MedicOneSystems\LivewireDatatable\LivewireDatatableServiceProvider"
php artisan migrate
  1. First Usage: Create a Livewire component:

    php artisan make:livewire Admin/UsersDatatable
    

    Update the generated component (app/Http/Livewire/Admin/UsersDatatable.php):

    use MedicOneSystems\LivewireDatatable\LivewireDatatable;
    use App\Models\User;
    
    class UsersDatatable extends LivewireDatatable
    {
        public function configure(): void
        {
            $this->setPrimaryKey('id');
            $this->setModel(User::class);
            $this->setSearch(['name', 'email']);
            $this->setPerPage(10);
        }
    
        public function columns(): array
        {
            return [
                'name' => 'Name',
                'email' => 'Email',
                'created_at' => 'Created At',
            ];
        }
    }
    
  2. Render the Datatable:

    @livewire('admin.users-datatable')
    

Key First Use Case

Replace a basic Laravel paginated list with a feature-rich datatable in minutes. For example, transform a simple User::paginate(10) into a sortable, filterable, and searchable grid with minimal code.


Implementation Patterns

Core Workflow

  1. Model Binding: Bind to Eloquent models or query builders. For complex queries, use the setQuery() method:

    public function configure(): void
    {
        $this->setQuery(User::where('active', true));
    }
    
  2. Column Configuration: Define columns with custom formatting:

    public function columns(): array
    {
        return [
            'name' => 'Name',
            'email' => (new Column('email'))
                ->sortable()
                ->searchable()
                ->format(fn($value) => '<a href="mailto:'.$value.'">'.$value.'</a>'),
            'role' => (new Column('role'))
                ->format(fn($value) => ucfirst($value)),
        ];
    }
    
  3. Filtering: Add filters via addColumn() or setFilters():

    public function configure(): void
    {
        $this->setFilters([
            'role' => 'select',
            'active' => 'boolean',
            'created_at' => 'date-range',
        ]);
    }
    
  4. Mass Actions: Add bulk actions (e.g., delete, export):

    public function configure(): void
    {
        $this->setActions([
            'delete' => 'Delete',
            'export' => 'Export',
        ]);
    }
    
    public function deleteSelected()
    {
        $this->selected()->delete();
    }
    
  5. Column Groups: Group related columns for better UX:

    public function columns(): array
    {
        return [
            'contact' => [
                'name' => 'Name',
                'email' => 'Email',
                'phone' => 'Phone',
            ],
            'status' => [
                'active' => 'Active',
                'role' => 'Role',
            ],
        ];
    }
    

Integration Tips

  • Tailwind CSS: The package includes Tailwind classes for styling. Customize via the setTableClasses() method:

    public function configure(): void
    {
        $this->setTableClasses('min-w-full divide-y divide-gray-200');
    }
    
  • Alpine.js: Leverage Alpine for dynamic interactions (e.g., tooltips, modals):

    <td x-data="{ tooltip: false }" @mouseenter="tooltip = true" @mouseleave="tooltip = false">
        <span x-text="value"></span>
        <span x-show="tooltip" x-transition class="absolute z-10 bg-gray-800 text-white text-xs rounded">
            Tooltip content
        </span>
    </td>
    
  • Livewire Hooks: Use Livewire hooks for pre/post actions:

    public function boot()
    {
        $this->dispatchBrowserEvent('datatable-ready');
    }
    
  • API Integration: Fetch data from external APIs by overriding getData():

    public function getData(): array
    {
        $response = Http::get('https://api.example.com/users');
        return $response->json();
    }
    

Gotchas and Tips

Common Pitfalls

  1. Performance:

    • Avoid eager-loading unnecessary relationships in configure(). Use with() sparingly:

      // Bad: Loads all relationships for all rows
      $this->setModel(User::with('posts', 'comments')->get());
      
      // Good: Load only what's needed
      $this->setModel(User::class);
      $this->addColumn('posts_count', 'Posts', fn($row) => $row->posts->count());
      
    • For large datasets, use setPerPage(50) or implement cursor-based pagination.

  2. Column Formatting:

    • Ensure formatted columns return strings or HTML-safe content. Avoid raw user input to prevent XSS:
      // Safe
      'name' => fn($value) => htmlspecialchars($value),
      
      // Unsafe (if $value is user-provided)
      'name' => fn($value) => $value,
      
  3. Filter Conflicts:

    • Filters may conflict with search. Exclude columns from search using setSearch():
      $this->setSearch(['name', 'email']); // Only search these columns
      
  4. Livewire State:

    • The package caches datatable state in Livewire’s session. Clear cache manually if needed:
      public function resetState()
      {
          $this->reset();
      }
      
  5. Unmaintained Package:

    • Since the package is unmaintained, fork and extend it if critical features are missing. Key areas to customize:
      • Query Builder: Extend MedicOneSystems\LivewireDatatable\Traits\QueryBuilder for complex joins.
      • Filters: Add custom filter types in app/Providers/AppServiceProvider.php:
        LivewireDatatable::addFilter('custom', CustomFilter::class);
        

Debugging Tips

  1. Log Queries: Enable query logging in AppServiceProvider:

    public function boot()
    {
        if (config('app.debug')) {
            DB::enableQueryLog();
        }
    }
    

    Log queries in your datatable component:

    public function getData(): array
    {
        $this->logQueries();
        return $this->query()->paginate($this->perPage)->toArray();
    }
    
  2. Inspect State: Dump Livewire state to debug filtering/sorting:

    public function mount()
    {
        $this->dispatchBrowserEvent('alert', ['message' => json_encode($this->state)]);
    }
    
  3. Tailwind Conflicts: If styles break, override Tailwind classes in your component’s Blade file:

    @push('styles')
        <style>
            .livewire-datatable th { background-color: #f8fafc !important; }
        </style>
    @endpush
    

Extension Points

  1. Custom Columns: Create reusable column types in app/Models/Columns/CustomColumn.php:

    namespace App\Models\Columns;
    
    use MedicOneSystems\LivewireDatatable\Column;
    
    class CustomColumn extends Column
    {
        public function __construct($column, $label = null)
        {
            parent::__construct($column, $label);
            $this->addClass('text-blue-500');
        }
    }
    

    Use it in columns():

    'custom' => new CustomColumn('email', 'Custom Email'),
    
  2. Custom Actions: Extend mass actions with custom logic:

    public function archiveSelected()
    {
        $this->selected()->update(['archived_at' => now()]);
        $this->dispatchBrowserEvent('alert', ['message' => 'Items archived!']);
    }
    
  3. Localization: Override default labels (e.g., "No results found") in config/livewire-datatable.php:

    'labels' => [
        'no_results' => 'No matching records found.',
    ],
    
  4. Server-Side Processing: For large datasets, implement server-side processing by overriding getData():

    public function getData(): array
    {
        return $this->query()
            ->forPage($this->page, $this->perPage)
            ->get()
            ->map(fn($row) => $this->formatRow($row))
    
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.
comsave/common
alecsammon/php-raml-parser
chrome-php/wrench
lendable/composer-license-checker
typhoon/reflection
mesilov/moneyphp-percentage
mike42/gfx-php
bookdown/themes
aura/view
aura/html
aura/cli
povils/phpmnd
nayjest/manipulator
omnipay/tests
psr-mock/http-message-implementation
psr-mock/http-factory-implementation
psr-mock/http-client-implementation
voku/email-check
voku/urlify
rtheunissen/guzzle-log-middleware