I have a table with items. I use cookies to save them. Also, I have two buttons (increase and decrease). When I press them to change qty it works, but it also puts the item's row to the bottom of the list. I need to keep them in the same position where they are. I used sortDirection prop to TableCell component to make an order, but it also didn't work. Please help update the code so I can keep items in the same position.
Thanks in advance.
export default function CartItemsTable() {
const [cookies, setCookie, removeCookie] = useCookies();
function IncreaseQTY(article) {
var newCookie = cookies[article];
newCookie.qty++;
setCookie(article, newCookie, {
expires: new Date(Date.now() + 604800000),
});
}
function DecreaseQTY(article) {
var newCookie = cookies[article];
newCookie.qty--;
if (newCookie.qty === 0) {
removeCookie(article);
} else {
setCookie(article, newCookie, {
expires: new Date(Date.now() + 604800000),
});
}
}
return (
<TableContainer component={Paper}>
<Table sx={{ minWidth: 650 }} >
<TableHead>
<TableRow>
<TableCell >Name</TableCell>
<TableCell sortDirection="asc" align="center">Code</TableCell>
<TableCell align="center">Price</TableCell>
<TableCell align="center">QTY</TableCell>
<TableCell align="center">Total</TableCell>
</TableRow>
</TableHead>
<TableBody>
{Object.keys(cookies).map(function (key, index) {
return (
<TableRow
key={index}
sx={{ "&:last-child td, &:last-child th": { border: 0 } }}
>
<TableCell component="th" scope="row">
{cookies[key].name}
</TableCell>
<TableCell align="center">{cookies[key].article}</TableCell>
<TableCell align="center">{cookies[key].price}</TableCell>
<TableCell align="center">
<ButtonGroup
variant="contained"
aria-label="outlined primary button group"
>
<Button
onClick={() => {
DecreaseQTY(cookies[key].article);
}}
>
-
</Button>
<Button variant="text" disableRipple={true}>
{cookies[key].qty}
</Button>
<Button
onClick={() => {
IncreaseQTY(cookies[key].article);
}}
>
+
</Button>
</ButtonGroup>
</TableCell>
<TableCell align="center">
{cookies[key].qty * cookies[key].price}
</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
</TableContainer>
);
}
Before I press the button
After I press the increase button, first line went to the bottom
Update
I guess this problem can be occurred because of the cookies order or even related to react-cookie package, so I added console.log(cookies); to IncreaseQTY function. After a couple increasing it starts to show this way
Related
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>
</>
)
}
const ResultsAccordion = ({projects, projectStatus}) =>
{
return (
<Accordion>
<AccordionSummary expandIcon={<ExpandMoreIcon />} aria-controls="panel1a-content" id="panel1a-header">
<Typography>{projectStatus}</Typography>
</AccordionSummary>
<AccordionDetails>
<TableContainer component={Paper} sx={{my:2 }}>
<Table>
<TableHead>
<TableRow style={{ width:"100%" }}>
<TableCell align="center">Team Name</TableCell>
<TableCell align="center">Project Link</TableCell>
<TableCell align="center">Team Members</TableCell>
</TableRow>
</TableHead>
<TableBody>
{
projects.map((value) =>
{
return (
<TableRow key={value.name}>
<TableCell align="center">
{value.name}
</TableCell>
<TableCell align="center">
<Link href={value.repo}>Project Repo</Link>
</TableCell>
<TableCell align="center">
<Stack direction="row" spacing={1} alignContent="center">
{
(value.members).map((item, key) =>
{
return (
<Chip key={key} component="a" href={`https://github.com/${item.github}`} clickable label={item.github} avatar={<Avatar alt={item.github} src={item.avatar}/> } />
);
})
}
</Stack>
</TableCell>
</TableRow>
);
})
}
</TableBody>
</Table>
</TableContainer>
</AccordionDetails>
</Accordion>
);
};
Chips are supposed to be returned in the Table Cell with Stack..
But there is no one.
I used the react Developers tools and there is no childrens in Stack.
The chips are rendered if i made any changes in the prop using ReactDevTools
I checked, the value.members array & it is also not empty.
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>
I think this is an easy problem, but I am struggling to understand how to do this since I don't have a class. I am trying to make this table sortable. I want to be able to sort based on the column that is clicked on.
Do I need to add a class? I am very new to ReactJS. Thanks for your help!
function CreateGradeTable(props) {
return (
<div>
<Table>
<TableHead>
<TableRow>
<TableCell className={props.tHead}>Student</TableCell>
<TableCell className={props.tHead}>Course</TableCell>
<TableCell className={props.tHead}>Term</TableCell>
<TableCell className={props.tHead}>Grade</TableCell>
<TableCell className={props.tHead}>Final</TableCell>
</TableRow>
</TableHead>
<TableBody>
{props.data.map((gradeDetail, i) => {
const {
gradeId,
courseName,
courseId,
studentName,
studentId,
courseTerm,
grade,
finalGradeForTerm,
} = gradeDetail;
return (
<TableRow
key={gradeId}
className={`${props.tRow} ${i % 2 !== 0 ? props.striped : ''}`}
>
<TableCell>
<Link to={`/student/${studentId}`}>
<StyledLink>{studentName}</StyledLink>
</Link>
</TableCell>
<TableCell>
<Link to={`/course/${courseId}`}>
<StyledLink>{courseName}</StyledLink>
</Link>
</TableCell>
<TableCell align="left">{courseTerm}</TableCell>
<TableCell align="left">{grade}</TableCell>
<TableCell align="left">{finalGradeForTerm}</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
</div>
);
}
I see that you are using Material-UI to display the table.
You need to use 'TableSortLabel' to display Header. This will also show ascending/descending arrows.
Then write an onClick handler on TableSortLabel to change state thus triggering re-render.
See the working example here
https://codesandbox.io/s/condescending-beaver-q0owe?fontsize=14
<TableBody>
{
props.data.sort(order === 'asc'? ascCompare: desCompare ).map((gradeDetail, i) => {
const {
grade,
courseName,
studentName,
} = gradeDetail;
return (
<TableRow
key={i}
>
<TableCell align="left">{grade}</TableCell>
<TableCell align="left">{studentName}</TableCell>
<TableCell align="left">{courseName}</TableCell>
</TableRow>
);
})}
</TableBody>
I have a list users, those details want to show in table format. Want to check if map has value, if not show the message 'no data found'.
how can I achieve that.?
{filteredList && filteredList
.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
.map(row =>
( row===null ? (
<TableRow key={row.id}>
<TableCell className={classes.tableCell}>{items++}</TableCell>
<TableCell className={classes.tableCell}>
{row.sp_Name}
</TableCell>
<TableCell className={classes.tableCell}>{row.sp_Phone}</TableCell>
<TableCell className={classes.tableCell}>{row.sp_Role}</TableCell>
<TableCell className={classes.tableCell}>{row.sp_Service}</TableCell>
<TableCell className={classes.tableCell}>{row.sp_Location}</TableCell>
<TableCell className={classes.tableCell}>
<Link to={'/admin/profile/' + row.id} key={row.id} style={{ textDecoration: "none" }} >
<Chip
icon={<FaceIcon />}
label="View Profile/Action"
color="primary"
className={classes.chip}
variant="outlined"
onClcik={this.handleAction}
/>
</Link>
</TableCell>
<TableCell className={classes.tableCell}>
<Tooltip title="Delete">
<DeleteIcon color="danger" onClick={() => this.handleClickDialogOpen(row.id)} className={classes.icon} />
{/* <DeleteIcon onClick={() => deleteSP(row.id)} className={classes.icon} /> */}
</Tooltip>
</TableCell>
</TableRow>
) : "no data"
)
)}
Your can check if data exist first, if yes, render the table and row. If no data,
then you just render the required 'no data found' text
getData = () => {
const filteredList = this.state.list // your logic to get data
// Perform your logic to filter the data
return filteredList.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
}
render() {
const filteredList = this.getData()
return (
filteredList.length > 0 ?
<table>
{data.map( /* Make your <tr> */ )}
</table> :
"no data found"
)
}