I’m trying to display a table that has selectable rows that I will later send with a form to my controller.
For now I got it working but my problem is that in the same table I got a search box and a pagination. They both work together ok but when I have selected rows and then try to search or paginate I lose the state of my selected rows.
This is my component:
import React, {useState} from 'react';
import Input from "@/Components/Form/Input";
import { Inertia } from "@inertiajs/inertia";
import {usePage, useForm, useRemember} from "@inertiajs/inertia-react";
import Main from "../../Layouts/Main"
import Table from "@/Components/Table/Table";
import Search from "@/Components/Search";
import ErrorForm from "@/Components/Form/ErrorForm";
import Paginator from "@/Components/Table/Paginator";
import {usePrevious} from "react-use";
const Create = () => {
const cuentas = usePage().props.cuentas.data
const links = usePage().props.cuentas.links
const { data, processing, errors } = useForm({
codigoPartida : '',
nombrePartida : '',
tipoPartida : 'gasto',
cuentas : []
})
function submit(e) {
e.preventDefault()
data.codigoPartida = document.getElementById('codigoPartida').value
data.nombrePartida = document.getElementById('nombrePartida').value
document.querySelectorAll('.row-select').forEach(function(item){
if(!data.cuentas.includes(item)){
if(item.checked){
data.cuentas.push(item.value)
}
}
});
console.log(data)
//Inertia.post('/nueva-partida-presupuestaria',data)
}
function handleChange(e){
if(e.target.checked){
document.querySelectorAll('.row-select').forEach(function(item){
item.checked = true
})
}else{
document.querySelectorAll('.row-select').forEach(function(item){
item.checked = false
})
}
}
return (
<>
<div className="flex justify-between mb-2">
<h2>Alta Partida Presupuestaria</h2>
</div>
<form className="create-form" id="create-form" onSubmit={submit}>
<Input
name="codigoPartida"
type="text"
id="codigoPartida"
placeholder="Código"
/>
{errors.codigoPartida &&
<ErrorForm
content={errors.codigoPartida}
/>
}
<Input
name="nombrePartida"
type="text"
id="nombrePartida"
placeholder="Descripción"
/>
{errors.codigoPartida &&
<ErrorForm
content={errors.codigoPartida}
/>
}
<button className="btn-consejo" type="submit" disabled={processing}>Crear</button>
</form>
<h2>Agregar Cuenta Contable</h2>
<div className="flex justify-between">
<Search />
</div>
<table className="min-w-full">
<thead>
<tr>
<th>
<input
id="select-all"
name="select-all"
type="checkbox"
onChange={handleChange}
/>
</th>
<th 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">Codigo</th>
<th 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">Cuenta</th>
<th 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">Clase</th>
</tr>
</thead>
<tbody>
{cuentas.map(({ id, COD_CUENTA, DESC_CUENTA, ID_CLASE_CUENTA }) => {
return (
<tr key={id}>
<td><input type="checkbox" value={id} name="row-select" className="row-select" /></td>
<td>{COD_CUENTA}</td>
<td>{DESC_CUENTA}</td>
<td>{ID_CLASE_CUENTA}</td>
</tr>
)
})}
{cuentas.length === 0 && (
<tr>
<td colSpan="4">
No se encontraron cuentas disponibles.
</td>
</tr>
)}
</tbody>
</table>
<Paginator links={links} />
</>
);
}
Create.layout = page => <Main title="Alta Partida Presupuestaria" children={page} />
export default Create
And also my Paginator and Search Components:
import React from 'react';
import { InertiaLink } from '@inertiajs/inertia-react';
const PageLink = ({ active, label, url }) => {
return (
<InertiaLink href={url} preserveState>
<span dangerouslySetInnerHTML={{ __html: label }}></span>
</InertiaLink>
);
};
// Previous, if on first page
// Next, if on last page
// and dots, if exists (...)
const PageInactive = ({ label }) => {
return (
<div dangerouslySetInnerHTML={{ __html: label }} />
);
};
export default ({ links = [] }) => {
// dont render, if there's only 1 page (previous, 1, next)
if (links.length === 3) return null;
return (
<div className="flex flex-wrap mt-6 -mb-1">
{links.map(({ active, label, url }) => {
return url === null ? (
<PageInactive key={label} label={label} />
) : (
<PageLink key={label} label={label} active={active} url={url} />
);
})}
</div>
);
};
import React, { useState, useEffect, useRef } from 'react';
import { Inertia } from '@inertiajs/inertia';
import {usePage, useRemember} from '@inertiajs/inertia-react';
import { usePrevious } from 'react-use';
import pickBy from 'lodash/pickBy';
export default () => {
const { filters } = usePage().props;
const [values, setValues] = useState({
search: filters.search || '',
});
const prevValues = usePrevious(values);
useEffect(() => {
// https://reactjs.org/docs/hooks-faq.html#how-to-get-the-previous-props-or-state
if (prevValues) {
const query = pickBy(values)
Inertia.get(route(route().current()), query, {
replace: true,
preserveState: true
});
}
}, [values]);
function handleChange(e) {
const key = e.target.name;
const value = e.target.value;
setValues(values => ({
...values,
[key]: value
}));
}
return (
<div className="flex items-center w-full max-w-md mr-4">
<div className="relative flex w-full bg-white rounded shadow">
<input
className="relative w-full px-6 py-3 rounded-r focus:outline-none focus:ring-2 focus:ring-indigo-400"
autoComplete="off"
type="text"
name="search"
name="search"
value={values.search}
onChange={handleChange}
placeholder="Search…"
/>
</div>
</div>
)
}
How would I go to get the expected behaviour. I’m kind of new to react.
I would really appreciate the help!
Image of the UI