How to add pagination for Collapsible table mui in reactjs - reactjs

I have an Collapsible table example here. But I don't know that how to add pagination for it. Any one have an idea ? Tks for all the help!
Example: https://codesandbox.io/s/p0td1n?file=/demo.tsx

Adding pagination to the table has no effect on being collapsible. So you can add it like this:
export default function CollapsibleTable() {
const [page, setPage] = React.useState(0);
const [rowsPerPage, setRowsPerPage] = React.useState(5);
const currentRows = rows.filter((r, ind) => {
return ind >= rowsPerPage * page && ind < rowsPerPage * (page + 1);
});
const handleChangePage = (event: unknown, newPage: number) => {
setPage(newPage);
};
const handleChangeRowsPerPage = (
event: React.ChangeEvent<HTMLInputElement>
) => {
setRowsPerPage(parseInt(event.target.value, 10));
setPage(0);
};
return (
<TableContainer component={Paper}>
<Table aria-label="collapsible table">
<TableHead>
<TableRow>
<TableCell />
<TableCell>Dessert (100g serving)</TableCell>
<TableCell align="right">Calories</TableCell>
<TableCell align="right">Fat (g)</TableCell>
<TableCell align="right">Carbs (g)</TableCell>
<TableCell align="right">Protein (g)</TableCell>
</TableRow>
</TableHead>
<TableBody>
{currentRows.map((row) => (
<Row key={row.name} row={row} />
))}
</TableBody>
</Table>
<TablePagination
rowsPerPageOptions={[5, 10, 25]}
component="div"
count={rows.length}
rowsPerPage={rowsPerPage}
page={page}
onPageChange={handleChangePage}
onRowsPerPageChange={handleChangeRowsPerPage}
/>
</TableContainer>
);
}
You can take a look at this sandbox for a live working example of collapsible table with pagination.

Related

My useEffect is not working. It is not getting called

I tried to get the users data through a useEffect and useEffect is not getting called. This is my allUsers.js file. Backend API is working and the UserService file is also working fine. I am only getting the first console log printed as mg. other console logs are not being printed.
export default function ViewUsers() {
const [userList, setUserList] = useState('');
console.log(userList,"mg")
useEffect(() => {
handleUser()
console.log("sas")
}, [])
const handleUser = async () =>{
const users = await UserService.viewUser()
setUserList(users);
console.log(userList,"user")
}
console.log(userList ,"1gmg")
return (
<>
<TableContainer component={Paper}>
<Table sx={{ minWidth: 650 }} aria-label="simple table">
<TableHead>
<TableRow>
<TableCell>Name</TableCell>
<TableCell align="right">Email</TableCell>
<TableCell align="right">Birth date</TableCell>
</TableRow>
</TableHead>
<TableBody>
{userList.map((row) => (
<TableRow
key={row.id}
sx={{ '&:last-child td, &:last-child th': { border: 0 } }}
>
<TableCell component="th" scope="row">
{row.name}
</TableCell>
<TableCell align="right">{row.email}</TableCell>
<TableCell align="right">{row.birthDate}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
</>
)
}

reactjs conditional statement inside TableCell

How do I input conditional if else statement in a TableCell for ReactJS. I want the data table to output nothing is found if the search box returns nothing.
Here is the code:
export default function DataTable () {
const [query, setQuery] = useState('')
const [tableData, setTableData] = useState([])
useEffect( function () {
const fetchUsers = async function () {
const response = await axios.get(`/search/?query=${query}`)
setTableData(response.data)
}
if (query.length === 0 || query.length > 2) fetchUsers()
}, [query])
return (
<>
<input type={'text'} placeholder={'Enter Teacher ID Number....'} className='search-bar' onChange={(event) => setQuery(event.target.value)} />
<TableContainer component={Paper} className='data-table'>
<Table sx={{minWidth: 650}} aria-label='simple table'>
<TableHead>
<TableRow>
<TableCell className='tableCell'>ID</TableCell>
<TableCell className='tableCell'>Name</TableCell>
<TableCell className='tableCell'>Surname</TableCell>
<TableCell className='tableCell'>Title</TableCell>
<TableCell className='tableCell'>Email</TableCell>
<TableCell className='tableCell'>Action #1</TableCell>
<TableCell className='tableCell'>Action #2</TableCell>
</TableRow>
</TableHead>
<TableBody>
{ tableData.map((data) => (
<TableRow key={data.id} sx={{ '&:last-child td, &:last-child th': {border:0}}}>
<TableCell className='tableCell'> { data.id }</TableCell>
<TableCell className='tableCell'> { data.name }</TableCell>
<TableCell className='tableCell'> { data.surname }</TableCell>
<TableCell className='tableCell'> { data.title }</TableCell>
<TableCell className='tableCell'> { data.email}</TableCell>
<TableCell className='tableCell'>
<button className={'verify'}>
<Link to={`/search/${data.id}`} className={'verify'} state={data}>Verify</Link>
</button>
</TableCell>
<TableCell className='tableCell'>
<button className={`drop`}>
<Link to={`/drop/${data.id}`} className={'drop'} state={data}>Drop</Link>
</button>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
</>
)
}
I tried to input ternary operator '?' but it returns the first result
First of all I recommend to you separate the mapped Row in a separated component to handle easily and get the code more readable. This component could be in other file.
On the other hand I highly recommend if you are consuming the data from rest service, is using React Query.
export default function DataTable () {
const [query, setQuery] = useState('')
const [tableData, setTableData] = useState([])
useEffect( function () {
const fetchUsers = async function () {
const response = await axios.get(`/search/?query=${query}`)
setTableData(response.data)
}
if (query.length === 0 || query.length > 2) fetchUsers()
}, [query])
function UserTableRow(user){
return (
<TableRow key={user.id} sx={{ '&:last-child td, &:last-child th': {border:0}}}>
<TableCell className='tableCell'> { user.id }</TableCell>
<TableCell className='tableCell'> { user.name }</TableCell>
<TableCell className='tableCell'> { user.surname }</TableCell>
<TableCell className='tableCell'> { user.title }</TableCell>
<TableCell className='tableCell'> { user.email}</TableCell>
<TableCell className='tableCell'>
<button className={'verify'}>
<Link to={`/search/${user.id}`} className={'verify'} state={data}>Verify</Link>
</button>
</TableCell>
<TableCell className='tableCell'>
<button className={`drop`}>
<Link to={`/drop/${user.id}`} className={'drop'} state={data}>Drop</Link>
</button>
</TableCell>
</TableRow>
)
}
return (
<>
<input type={'text'} placeholder={'Enter Teacher ID Number....'} className='search-bar' onChange={(event) => setQuery(event.target.value)} />
<TableContainer component={Paper} className='data-table'>
<Table sx={{minWidth: 650}} aria-label='simple table'>
<TableHead>
<TableRow>
<TableCell className='tableCell'>ID</TableCell>
<TableCell className='tableCell'>Name</TableCell>
<TableCell className='tableCell'>Surname</TableCell>
<TableCell className='tableCell'>Title</TableCell>
<TableCell className='tableCell'>Email</TableCell>
<TableCell className='tableCell'>Action #1</TableCell>
<TableCell className='tableCell'>Action #2</TableCell>
</TableRow>
</TableHead>
<TableBody>
{ tableData?.map((user) => <UserTableRow user={user}/>)}
{!tableData.length && <div>No results found.</div>}
</TableBody>
</Table>
</TableContainer>
</>
)
}

React - How to break a line in a cell of a material ui table

I'm using the DenseTable component of the ui material and wanted to break a string into parts
here is my table:
I want in the cursos column, in the line that has LEIT - 1st Ano/LEE - 1st Ano I want to break the string where there is the '/'
below my DenseTable component code:
function createData(aulaID, numAula, tipoAula, nome, curso, data, acao) {
return { aulaID, numAula, tipoAula, nome, curso, data, acao };
}
export default function DenseTable() {
const { selectedRow, setSelectedRow, cursoSigla } = useListarAulas();
const [rows, setRows] = React.useState([]);
const {
showLancarSumarioModal,
handleOpenLancarSumarioModal,
handleCloseLancarSumarioModal,
} = useEscreverSumario();
const {
aulas,
// docente,
} = useFiltrarAulas();
React.useEffect(() => {
if (rows.length !== aulas.length) {
const tempRows = [];
aulas.map((aula) =>
tempRows.push(
createData(
aula.id,
aula.numero,
aula.tipo,
aula.disciplina.codigo,
cursoSigla(aula.cursos),
aula.data,
'Lançar Sumario'
)
)
);
setRows(tempRows);
}
}, [aulas, rows]);
return (
<>
<TableContainer component={Paper}>
<Table sx={{ minWidth: 650 }} size="small" aria-label="a dense table">
<TableHead>
<TableRow>
<TableCell>Disciplina</TableCell>
<TableCell align="right">Curso</TableCell>
<TableCell align="right">Data</TableCell>
<TableCell align="right">Acção</TableCell>
</TableRow>
</TableHead>
<TableBody>
{rows.map((row) => (
<TableRow
key={row.nome}
sx={{ '&:last-child td, &:last-child th': { border: 0 } }}
>
<TableCell component="th" scope="row">
{row.nome}
</TableCell>
<TableCell align="right">{row.curso}</TableCell>
<TableCell align="right">
{row.data}
{/* moment(row.data).format('yyyy-MM-DD') */}
</TableCell>
<TableCell align="right">
<Button
size="small"
onClick={() => {
setSelectedRow(row);
handleOpenLancarSumarioModal();
}}
>
{row.acao}
</Button>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
<EscreverSumarioModal
showModal={showLancarSumarioModal}
handleCloseModal={handleCloseLancarSumarioModal}
selectedRow={selectedRow}
/>
</>
);
}
the function cursoSigla() in useEffect receives a courses object where their respective acronyms are and returns a string concatenated with the acronym of each course like this "LEIT - 1º Ano/LEE - 2º Ano"
below the function code:
function cursoSigla(cursos) {
const sigla = [];
if (cursos.length > 1) {
if (sigla.length !== cursos.length) {
cursos.map((curso) => sigla.push(`${curso.sigla} - ${curso.ano}º Ano`));
return sigla.join('/');
}
}
if (cursos.length === 1) {
sigla.push(cursos[0].sigla);
return `${sigla[0]} - ${cursos[0].ano}º Ano`;
}
console.log(sigla);
return '';
}
My question is how to introduce a line break in my table cell ?
Instead of rendering them as:
<TableCell align="right">{row.curso}</TableCell>
You could do something like this instead:
<TableCell>
{row.curso.split("/").map((curs, idx) => (
<p key={idx}>{curs}</p>
))}
</TableCell>

useEffect infinite loop WITH empty dependency array

I am dispatching a thunk from my useEffect to populate a table when the page loads. The useEffect keeps running infintely, even though I am using an empty dependency array. Here is my code:
const Cart = (props) => {
const [didFetch, setDidFetch] = useState(false);
useEffect( () => {
async function fetchCart(){
await props.getCartItems();
setDidFetch(true);
}
fetchCart()
return setDidFetch(false)
},[]);
return (
<TableContainer component={Paper}>
<Table sx={{ minWidth: 650 }} aria-label="simple table">
<TableHead>
<TableRow>
<TableCell>Product</TableCell>
<TableCell align="right">Quantity</TableCell>
<TableCell align="right">Total Cost</TableCell>
</TableRow>
</TableHead>
<TableBody>
{props.cartItems.map((item) => (
<TableRow
key={item.product.name}
sx={{ "&:last-child td, &:last-child th": { border: 0 } }}
>
<TableCell component="th" scope="row">
{item.product.name}
</TableCell>
<TableCell align="right">{item.quantity}</TableCell>
<TableCell align="right">
{(item.quantity * item.product.price).toFixed(2)}
</TableCell>
<TableCell>
<Button onClick={() => props.removeCartItem(item.id)}>
Remove
</Button>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
);
};
The cleanup function of useEffect should be an anonymous function, and you shouldn't set state variables inside it, as #windmaomao pointed out, it is a memory leak:
Suggestion
If you want to store a didFetch flag, I would use a ref for this purpose:
import {useRef} from 'react'
const Cart = (props) => {
const fetched = useRef()
useEffect( () => {
async function fetchCart(){
const res = await props.getCartItems();
if(res) fetched.current = true
}
fetchCart()
return () => fetched.current = false
},[]);
return (
<TableContainer component={Paper}>
<Table sx={{ minWidth: 650 }} aria-label="simple table">
<TableHead>
<TableRow>
<TableCell>Product</TableCell>
<TableCell align="right">Quantity</TableCell>
<TableCell align="right">Total Cost</TableCell>
</TableRow>
</TableHead>
<TableBody>
{props.cartItems.map((item) => (
<TableRow
key={item.product.name}
sx={{ "&:last-child td, &:last-child th": { border: 0 } }}
>
<TableCell component="th" scope="row">
{item.product.name}
</TableCell>
<TableCell align="right">{item.quantity}</TableCell>
<TableCell align="right">
{(item.quantity * item.product.price).toFixed(2)}
</TableCell>
<TableCell>
<Button onClick={() => props.removeCartItem(item.id)}>
Remove
</Button>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
);
};
Using your existing code it would be either:
Anonymous function
const [didFetch, setDidFetch] = useState(false);
useEffect( () => {
async function fetchCart(){
await props.getCartItems();
setDidFetch(true);
}
fetchCart()
return () => {
setDidFetch(false);
};
},[]);
Named Function
const [didFetch, setDidFetch] = useState(false);
useEffect( () => {
async function fetchCart(){
await props.getCartItems();
setDidFetch(true);
}
fetchCart()
return function cleanup() {
setDidFetch(false);
};
},[]);
Here are the useEffect docs for reference: https://reactjs.org/docs/hooks-effect.html

react-sortable-hoc stops after first move with edgeOffset

I'm attempting to make a sortable table with react-sortable-hoc. This works fine for the first move but afterwards, react-sortable-hoc will stop working. The row in the table no longer animates and attempting to move an item throws the following error:
TypeError: edgeOffset is undefined
This is the relevant code:
const DragHandle = SortableHandle(() => <DragIndicatorIcon />);
const SortableItem = SortableElement(({ value, sortIndex, groupType }) => {
return (
<TableRow
hover
key={value.id}
index={sortIndex}
>
<TableCell><DragHandle /></TableCell>
<TableCell component="th" scope="row">
{value.fullname}
</TableCell>
<TableCell numeric>{value.number}</TableCell>
{groupType &&
<TableCell>10</TableCell>
}
</TableRow>
);
});
const SortableList = SortableContainer(({ items, groupType }) => {
return (
<TableBody>
{items.map((user, index) => {
return (
<SortableItem key={`item-${index}`} groupType={groupType} index={index} sortIndex={index} value={user} />
);
})}
</TableBody>
);
});
And:
<Table className={classes.table}>
<TableHead>
<TableRow>
<TableCell />
<TableCell>Name</TableCell>
<TableCell numeric>Number</TableCell>
{this.props.groupType === "1" &&
<TableCell>Seconds</TableCell>
}
</TableRow>
</TableHead>
<SortableList items={this.props.items} groupType={this.props.groupType === "1"} onSortEnd={this.props.onSortEnd} useDragHandle={true} useWindowAsScrollContainer={true} />
</Table>

Resources