resources/views/pages/frontend/docs/datatables-servidor.md
Última modificación: 24 Oct, 2026

Grillas de Datos KTDataTable Server-Side

Para soportar tablas con millones de registros sin penalizar la memoria del navegador, Mañuti prohíbe el renderizado estático de bucles @foreach en listados administrativos. Estandariza la arquitectura KTDataTable Server-Side alimentada por APIs JSON.


1. El Patrón de Controlador API

El controlador implementa un método data(Request $request) que resuelve búsqueda, ordenamiento y paginación a nivel de motor de base de datos:

// app/Http/Controllers/Admin/UserController.php
public function data(Request $request)
{
    $query = Usuario::with(['roles', 'estatus']);

    // 1. Búsqueda Global Servidor
    if ($search = $request->input('search')) {
        $query->where(function ($q) use ($search) {
            $q->where('nombres', 'like', "%{$search}%")
              ->orWhere('correo', 'like', "%{$search}%")
              ->orWhere('usuario', 'like', "%{$search}%");
        });
    }

    // 2. Ordenamiento Dinámico
    $sortField = $request->input('sortField', 'created_at');
    $sortOrder = $request->input('sortOrder', 'desc');
    $query->orderBy($sortField === 'null' ? 'created_at' : $sortField, $sortOrder);

    // 3. Paginación en Base de Datos
    $perPage = (int) $request->input('pageSize', 10);
    $users = $query->paginate($perPage);

    // 4. Transformación de Filas
    $data = $users->getCollection()->transform(function ($u) {
        return [
            'id'         => $u->id,
            'name'       => $u->nombres . ' ' . $u->apellido_paterno,
            'email'      => $u->correo,
            'roles'      => $u->roles->map(fn($r) => ['name' => $r->name]),
            'status'     => $u->estatus?->etiqueta ?? 'Sin estatus',
            'created_at' => $u->created_at->format('d/m/Y'),
        ];
    });

    return response()->json([
        'data'       => $data,
        'totalCount' => $users->total(),
        'page'       => $users->currentPage(),
        'pageSize'   => $users->perPage(),
        'totalPages' => $users->lastPage()
    ]);
}

2. Consumo en Frontend y Búsqueda por Enter

El script de frontend consume el endpoint desacoplado de Blade, evitando saturar el servidor en cada pulsación de tecla ejecutando la búsqueda exclusivamente al presionar Enter:

// resources/js/admin/users.js
var datatable = new KTDataTable(datatableEl, {
    apiEndpoint: configEl.dataset.apiUrl,
    requestMethod: 'GET',
    search: { delay: 400, key: 'search' },
    mapResponse: (response) => response,
    columns: {
        name: {
            title: 'Usuario',
            render: (value, row) => `
                <div class="flex items-center gap-3">
                    <span class="font-bold text-gray-800">${value}</span>
                    <span class="text-xs text-gray-400">${row.email}</span>
                </div>`
        },
        // ...
    },
    pageSize: 10
});

// Listener exclusivo de tecla Enter
searchInput.addEventListener('keyup', function (e) {
    if (e.key === 'Enter') {
        datatable.search(e.target.value);
    }
});

Enlaces Relacionados

Edita este documento en >> datatables-servidor.md
← Volver a la Landing Page