Hi everyone!
I'm having some issues implementing pagination for a collection. So this is my relevant code:
My controller method:
public function create(): Response
{
// Primero obtengo el plan de cuentas
$response = HTTP::get('http://localhost:8001/api/cuentas');
$plan_de_cuentas = collect($response->json());
// Después tengo que filtrar el plan de cuentas sacando aquellas que ya esten siendo utilizadas en otras partidas
$cuentas_utilizadas = DB::table('account_budget')->get();
$plan_de_cuentas = $plan_de_cuentas->reject(function($value,$key) use($cuentas_utilizadas){
return $cuentas_utilizadas->contains('id_cuenta_tango',$value['ID_CUENTA']);
});
// Luego tengo que armar la paginacion y enviar solo la data que quiero mostrar
$plan_de_cuentas = $plan_de_cuentas->map(function($cuenta){
return collect($cuenta)->only('COD_CUENTA','DESC_CUENTA','TIPO_CUENTA')->toArray();
});
$plan_de_cuentas = CollectionHelper::paginate($plan_de_cuentas,20);
return Inertia::render('PartidasPresupuestarias/Create',[
'cuentas' => $plan_de_cuentas,
'filters' => Request::only(['search'])
]);
}
My CollectionHelper:
<?php
namespace App\Helpers;
use Illuminate\Container\Container;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Pagination\Paginator;
use Illuminate\Support\Collection;
class CollectionHelper
{
public static function paginate(Collection $results, $pageSize)
{
$page = Paginator::resolveCurrentPage('page');
$total = $results->count();
return self::paginator($results->forPage($page, $pageSize), $total, $pageSize, $page, [
'path' => Paginator::resolveCurrentPath(),
'pageName' => 'page',
]);
}
/**
* Create a new length-aware paginator instance.
*
* @param \Illuminate\Support\Collection $items
* @param int $total
* @param int $perPage
* @param int $currentPage
* @param array $options
* @return \Illuminate\Pagination\LengthAwarePaginator
*/
protected static function paginator($items, $total, $perPage, $currentPage, $options)
{
return Container::getInstance()->makeWith(LengthAwarePaginator::class, compact(
'items', 'total', 'perPage', 'currentPage', 'options'
));
}
}
My Two React Components:
import React from 'react';
import Main from "../../Layouts/Main"
import {InertiaLink, usePage} from "@inertiajs/inertia-react";
import Table from "@/Components/Table/Table";
import Search from "@/Components/Search";
const Create = () => {
const cuentas = usePage().props.cuentas.data
console.log(cuentas)
const titulos = ['Codigo','Cuenta','Clase']
const filters = usePage().props.filters
const links = usePage().props.cuentas.links
return (
<>
<h2>Alta Partida Presupuestaria</h2>
<h2>Agregar Cuenta Contable</h2>
<div className="flex justify-between">
<Search
filters={filters}
/>
</div>
<Table
titulos = {titulos}
contenido = {cuentas}
links = {links}
/>
</>
);
}
Create.layout = page => <Main title="Alta Partida Presupuestaria" children={page} />
export default Create
import React from "react";
import {InertiaLink, Link} from "@inertiajs/inertia-react";
export default function Table({titulos,contenido,links}) {
const titleItems = titulos.map((titulo) => <th key={titulo} className="px-6 py-3 text-xs font-medium leading-4 tracking-wider text-left text-gray-500 uppercase border-b border-gray-200 bg-gray-504">{titulo}</th>)
const contentItems = contenido.map((item,key) => {
const row = []
Object.values(item).forEach( (value,key) => {
if(typeof value != 'object'){
row.push(<td key={key}>{value}</td>)
}
})
return (
<tr key={key} className="px-6 py-4 whitespace-no-wrap">{row}</tr>
)
})
const paginationLinks = links.map((link) => <Link href={link.url}>{link.label}</Link>)
return (
<>
<table className="min-w-full">
<thead>
<tr>
{titleItems}
</tr>
</thead>
<tbody>
{contentItems}
</tbody>
</table>
<div className="mt-2">
{paginationLinks}
</div>
</>
);
}
The behaviour is really weird, basically my first page works ok and I can see all the pagination links. The problem is when I hit any other page it doesnt works because my array with the content for the table is not an array anymore is an object. If I console.log the conent on the first page that works and on the second i get the following:
Content from the first page (Working ok)
(20) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
0: {COD_CUENTA: '1.1.1.1.0.0.01', DESC_CUENTA: 'CAJA', TIPO_CUENTA: 'No monetaria'}
1: {COD_CUENTA: '1.1.1.1.0.0.02', DESC_CUENTA: 'FONDO FIJO', TIPO_CUENTA: 'No monetaria'}
2: {COD_CUENTA: '1.1.1.1.0.0.03', DESC_CUENTA: 'CAJA CHICA', TIPO_CUENTA: 'No monetaria'}
3: {COD_CUENTA: '1.1.1.1.0.0.04', DESC_CUENTA: 'EFECTIVO EN BUZON BCO. MACRO', TIPO_CUENTA: 'No monetaria'}
...
length: 20
[[Prototype]]: Array(0)
Content from the second page (Not working)
{20: {…}, 21: {…}, 22: {…}, 23: {…}, 24: {…}, 25: {…}, 26: {…}, 27: {…}, 28: {…}, 29: {…}, 30: {…}, 31: {…}, 32: {…}, 33: {…}, 34: {…}, 35: {…}, 36: {…}, 37: {…}, 38: {…}, 39: {…}}
20: {COD_CUENTA: '1.1.3.1.0.0.01', DESC_CUENTA: 'DEUDORES POR CERTIF. DE FIRMAS - CPCES', TIPO_CUENTA: 'No monetaria'}
21: {COD_CUENTA: '1.1.3.1.0.0.02', DESC_CUENTA: 'DEUDORES POR CERTIF. DE FIRMAS - C.S.S.', TIPO_CUENTA: 'No monetaria'}
22: {COD_CUENTA: '1.1.3.1.0.0.03', DESC_CUENTA: 'DEUDORES POR CERTIF. DE FIRMAS - HONORARIOS PROF.', TIPO_CUENTA: 'No monetaria'}
...
[[Prototype]]: Object
Note that on the first one I have an array and on the second one an Object, so the reason it doesnt works it's obvious, I'm trying to do a map on an object so it fails.
The question is why I have array on the first page of the pagination and an object on the second page. I really dont understand.