2 Inline Tables
Lenny P. edited this page 2026-10-07 08:35:44 +02:00

Inline Tables

Render the table directly

For a table-only component, keep the inherited render() method:

class Users extends PenguTable
{
    public function query(): Builder
    {
        return User::query();
    }

    public function columns(): array
    {
        return [
            Column::make('Name', 'name')->sortable()->searchable(),
        ];
    }
}
<livewire:users />

Render a table inside your own view

If the component has its own page layout or additional content, override render() and include the table with x-pengutable:

use Illuminate\Contracts\View\View;

public function render(): View
{
    return $this->view()
        ->layout('layouts.app')
        ->title('Users');
}
<div class="space-y-4">
    <x-page-header title="Users" />

    <x-card>
        <x-pengutable :configuration="$this" />
    </x-card>
</div>

The configuration value is the current PenguTable instance. It is passed to the Blade component, not stored as a separate public Livewire property. This is important because table definitions commonly contain closures and objects that should not be serialized as Livewire state.

Livewire 4 MFC example

The same pattern works in a Livewire 4 multi-file component. The PHP file extends PenguTable and the Blade file renders the table:

// resources/views/livewire/users.php
use App\Models\User;
use Illuminate\Database\Eloquent\Builder;
use RealZone22\PenguTables\Livewire\PenguTable;
use RealZone22\PenguTables\Table\Column;

new class extends PenguTable {
    public function query(): Builder
    {
        return User::query();
    }

    public function columns(): array
    {
        return [
            Column::make('Name', 'name')->sortable()->searchable(),
        ];
    }
};
{{-- resources/views/livewire/users.blade.php --}}
<div>
    <h1>Users</h1>

    <x-pengutable :configuration="$this" />
</div>

Component state

The inherited component keeps the following main state:

  • search
  • perPage
  • sortField
  • sortDirection
  • activeFilters
  • selected
  • selectAll

Do not duplicate these properties in the child component. Use the provided methods and configuration hooks instead.