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 Generic Table Laravel Package

cakmalik/livewire-generic-table

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Install the Package

    composer require cakmalik/livewire-generic-table
    

    Publish views if using Laravel < 10.21:

    php artisan vendor:publish --tag=livewire-generic-table-views
    
  2. Define Columns Create a $columns array in your controller or Blade file. Example:

    $columns = [
        ['label' => 'ID', 'field' => 'id', 'sortable' => true],
        ['label' => 'Name', 'field' => 'name', 'searchable' => true],
    ];
    
  3. Render the Table Use the component in Blade:

    <livewire:generic-table
        :model="'App\Models\User'"
        :columns="$columns"
        defaultSortField="name"
        defaultSortDirection="asc"
    />
    
  4. Volt-Specific Setup For Volt, define columns as a computed property:

    #[Computed]
    public function columns(): array
    {
        return [
            ['label' => 'ID', 'field' => 'id'],
            ['label' => 'Email', 'field' => 'email'],
        ];
    }
    

Implementation Patterns

Core Workflows

  1. Dynamic Column Configuration

    • Use the :columns prop to define table structure. Each column supports:
      • label: Display name.
      • field: Model attribute or accessor.
      • sortable: Enable sorting (default: false).
      • searchable: Enable global search (default: false).
      • renderer: Custom closure for cell formatting (e.g., badges, links).
    • Example with renderers:
      $columns = [
          [
              'label' => 'Status',
              'field' => 'status',
              'renderer' => fn($value) => "<span class='badge bg-$value'>$value</span>",
          ],
      ];
      
  2. Query Parameter Handling

    • Pass :queryParams to pre-filter results (e.g., search keywords, filters):
      <livewire:generic-table
          :model="'App\Models\Post'"
          :columns="$columns"
          :queryParams="['status' => 'published', 'keyword' => request('q')]"
      />
      
    • The component automatically hydrates the query based on these params.
  3. Row Actions

    • Define actions in the :actions prop (Volt: computed property):
      $actions = [
          'edit' => ['label' => 'Edit', 'icon' => 'edit'],
          'delete' => ['label' => 'Delete', 'icon' => 'trash'],
      ];
      
    • Emit events via $emit('action', $id, 'edit') in your Livewire class.
  4. Pagination

    • Customize per-page options with :perPageOptions:
      <livewire:generic-table
          :perPageOptions="[10, 25, 50]"
          perPage="25"
      />
      
  5. Integration with Volt

    • Volt’s lack of nested state requires computed properties for dynamic data:
      #[Computed]
      public function columns(): array { ... }
      
      #[Computed]
      public function actions(): array { ... }
      

Advanced Patterns

  • Custom Renderers: Use closures for complex cell formatting (e.g., avatars, status indicators):

    'renderer' => fn($user) => view('partials.user-avatar', ['user' => $user]),
    
  • Conditional Columns: Dynamically toggle columns based on user roles or permissions:

    $columns = auth()->user()->can('manage_users')
        ? array_merge($columns, [['field' => 'email', 'label' => 'Email']])
        : $columns;
    
  • Bulk Actions: Extend the component to support bulk operations (e.g., select-all checkboxes) by overriding the table’s template or using slots.

  • API Integration: For headless tables, pass an API response as the model and customize the query builder logic in the Livewire class.


Gotchas and Tips

Pitfalls

  1. Volt Nested State Limitation:

    • Issue: Volt cannot serialize nested arrays in state. Columns or actions defined directly in the component’s public array props will fail.
    • Fix: Use computed properties (#[Computed]) for dynamic arrays.
  2. Case-Sensitive Field Matching:

    • The component matches column field values against model attributes case-sensitively. Use accessors or normalize fields (e.g., snake_case) to avoid errors.
  3. Query Builder Overrides:

    • If you extend the Livewire class, ensure getTableQuery() is properly overridden to handle custom query logic (e.g., joins, scopes).
  4. Renderer Scope:

    • Renderer closures receive the entire model instance, not just the field value. Access related data via $model->relation.
  5. Pagination Conflicts:

    • If using custom pagination (e.g., cursor()), override getPagination() in your Livewire class to return the correct paginator.

Debugging Tips

  • Check Column Definitions: Validate your $columns array for typos in field names or missing required keys. Use dd($columns) to inspect the structure.

  • Query Logs: Enable Laravel query logging to verify the component’s SQL:

    DB::enableQueryLog();
    // ... run Livewire update ...
    dd(DB::getQueryLog());
    
  • Event Emission: Ensure row actions emit events with the correct payload:

    $this->emit('action', $id, 'edit'); // Format: event, id, action_name
    
  • View Publishing: If styles or views are missing, republish assets:

    php artisan vendor:publish --tag=livewire-generic-table-views --force
    

Extension Points

  1. Custom Templates: Override the default table view by publishing and modifying:

    php artisan vendor:publish --tag=livewire-generic-table-views
    

    Then extend the published resources/views/vendor/livewire-generic-table/table.blade.php.

  2. Add New Renderer Types: Extend the component by adding new renderer methods to the Livewire class (e.g., renderProgressBar()).

  3. Localization: Customize labels (e.g., "No results") by overriding the getTranslations() method or publishing the language file.

  4. Headless Mode: For SPAs or API-driven apps, disable the default table view and return data via $this->dispatch() or a custom event.

  5. Testing: Use Livewire’s testing helpers to assert table behavior:

    $this->assertSeeInOrder(['ID', 'Name'], $table);
    $this->assertSelected('25', $table->perPageSelect);
    
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.
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope