Tabs en pagina customizada de filamentPHP v4

Today

Tutorial

Introduccion

Bienvenido a esta serie de filamentPHP V4, en esta primera parte, vamos a explorar como integrar tabs en una tabla dentro de una pagina customizada de filamentPHP

¿Que son los tabs en una tabla de filament?

Los tabs son componentes situados como encabezados, que nos permiten hacer filtros masivos y rapidos sobre el contenido que tenemos en nuestra tabla.

trait HasTabs
{
    public ?string $activeTab = null;
    protected array $cachedTabs;
    protected function loadDefaultActiveTab(): void
    {
        if (filled($this->activeTab)) {
            return;
        }
        $this->activeTab = $this->getDefaultActiveTab();
    }
    ...
}

Filament trae el trait HasTabs que permite integrar tabs en cualquier tipo de paginas.

Metodos y funciones del componente

Estos son algunos de los metodos y funciones mas importantes, si deceas revisar a detalle el componente puedes seguir al codigo oficial en filamentPHP HasTabs

Metodo o Funcion Propósito
loadDefaultActiveTab() Carga el tab activo
getDefaultActiveTab() Devuelve el tab por defecto como activo
getTabs() Retorna una lista de tabs

¿Entonces como integramos en una pagina?

Usualmente cuando se crea una pagina con el comando php artisan make:filament-page NombrePagina ocurre que nos crea un archivo con el siguiente contenido basico.

<?php
namespace App\Filament\Pages;
use Filament\Pages\Page;
 
class CustomPageWithTabs extends Page
{
    protected string $view = 'filament.pages.custom-page-with-tabs';
}

y entonces que ocurre con esto?, absolutamente todo si es que queremos agregar tabs sobre nuestra tabla, cuando hacemos referencias a una vista $view filament vincula todo el contenido, funciones, metodos a ella. ejemplo si quisieramos agregar una tabla tendriamos que implementar el trait HasTables y configurar la vista de la siguiente manera.

<x-filament-panels::page>
    {{ $this->table }}
</x-filament-panels::page>

Removiendo la referencia a una vista

Para eliminar la referencia es tan sencillo como eliminar la linea en donde se menciona $view.

class PagosPendientes extends Page implements HasTable
{
    use InteractsWithTable;
    use HasTabs;
 
    protected static string|BackedEnum|null $navigationIcon = Heroicon::CurrencyDollar; 
    protected static ?string $navigationLabel = 'Pagos Pendientes';
    protected static ?string $title = 'Lista de pagos pendientes';
    protected ?string $subheading = 'Lista de todas las cuotas que aun faltan.';
}

entonces la pagina se preguntara, ¿donde deberia renderizar entonces?, en este caso se debe tambien de integrar las funciones y metodos

public function mount(): void
{
    $this->loadDefaultActiveTab(); 
    // ⬆ esto cargara el tab por defecto que siempre es el que esta en la posicion 0 del array ⬆
}
 
public function content(Schema $schema): Schema 
// ⬆ este metodo es el que hace de reemplazo a $view ⬆
{
    return $schema
        ->components([
            $this->getTabsContentComponent(), 
            // ⬆ esto renderizara la lisa de tabs dentro de la pagina ⬆
            EmbeddedTable::make(), 
            // ⬆ esto renderizara la tabla que se integra por la implementacion HasTable ⬆
        ]);
}

Funciones y metodos de HasTabs y HasTable

Luego de aver preparado los metodos para no usar una vista blade, debera agregar y configurar los metodos de HasTabs y HasTable para obtenere los datos

Metodo o Funcion Propósito Propiedad
getTableQuery() Usado para obtener datos de la DB HasTable
table(Table $table) Usado para definir, filtros, columnas, actions HasTable
getTabs() Retorna una lista de tabs HasTabs

getTableQuery - HasTable

protected function getTableQuery(): Builder|Relation|null
{
    return EstudiantePlanPago::query()->conCuotasPendientes(); 
    // EstudiantePlanPago es el modelo de donde se obtendran los datos
}

table - HasTable

public function table(Table $table): Table
{
    return $table
        ->poll('10s')
        ->deferLoading(true)
        ->modifyQueryUsing($this->modifyQueryWithActiveTab(...))
        // ⬆ este metodo es obligatorio, caso contrario los tabs no funcionaran ⬆
    ->columns([
        // Columnas de la tabla 
    ])
    ->filters([
        // Filtros de la tabla
    ]);
}

getTabs - HasTabs

// esto corresponde a su propia necesidad
public function getTabs(): array
{
    return [
        'todos' => Tab::make()
            ->label('Todos')
            ->badge(EstudiantePlanPago::conCuotasPendientes()->count()),        
        'pendientes' => Tab::make()
            ->label('Pendientes')
            ->badge(function () {
                $count = EstudiantePlanPago::conCuotasPendientes()
                    ->whereHas('estado', fn ($q) => $q->where('nombre', 'LIKE', '%pendiente%'))
                    ->count();
                return $count;
            })
            ->modifyQueryUsing(function (Builder $query) {
                return $query->whereHas('estado', fn ($q) => 
                    $q->where('nombre', 'LIKE', '%pendiente%')
                );
            }),
    ];
}

Entonces su pagina customizada tendra tabs para poder filtrar y moverse con mas facilidad

Resultados


© 2026 Krypton612. Todos los derechos reservados.