I am struggling to get this table to behave properly. I have set overflow-x to auto for the table. The table is very similar to the material-ui table from here: https://material-ui.com/demos/tables/
The table will shrink to a certain point and will then simply overflow the edge of the page.
gif of the behavior
Class EnhancedTableHead extends Component {
createSortHandler = property => event => {
this.props.onRequestSort(event, property);
};
render() {
const {
onSelectAllClick,
order,
orderBy,
numSelected,
rowCount
} = this.props;
return (
<TableHead>
<TableRow>
<TableCell padding="checkbox">
<Checkbox
indeterminate={numSelected > 0 && numSelected < rowCount}
checked={numSelected === rowCount}
onChange={onSelectAllClick}
/>
</TableCell>
{columnData.map(column => {
return (
<TableCell
key={column.id}
numeric={column.numeric}
padding={column.disablePadding ? 'none' : 'default'}
sortDirection={orderBy === column.id ? order : false}
>
<Tooltip
title="Sort"
placement={column.numeric ? 'bottom-end' : 'bottom-start'}
enterDelay={300}
>
<TableSortLabel
active={orderBy === column.id}
direction={order}
onClick={this.createSortHandler(column.id)}
>
{column.label}
</TableSortLabel>
</Tooltip>
</TableCell>
);
}, this)}
</TableRow>
</TableHead>
);
}
}
EnhancedTableHead.propTypes = {
numSelected: PropTypes.number.isRequired,
onRequestSort: PropTypes.func.isRequired,
onSelectAllClick: PropTypes.func.isRequired,
order: PropTypes.string.isRequired,
orderBy: PropTypes.string.isRequired,
rowCount: PropTypes.number.isRequired
};
const styles = theme => ({
root: {
width: '100%',
marginTop: theme.spacing.unit * 3
},
table: {
minWidth: 700
},
tableWrapper: {
overflowX: 'auto'
}
});
class Companies extends Component {
constructor(props, context) {
super(props, context);
this.state = {
order: 'asc',
orderBy: 'info',
selected: [],
data:
this.props.accounts.length > 0
? this.props.accounts.sort((a, b) => (a.name < b.name ? -1 : 1))
: [],
page: 0,
rowsPerPage: 3
};
}
render() {
const { classes } = this.props;
const { data, order, orderBy, selected, rowsPerPage, page } = this.state;
const emptyRows =
rowsPerPage - Math.min(rowsPerPage, data.length - page * rowsPerPage);
return (
<Paper className={classes.root}>
<EnhancedTableToolbar numSelected={selected.length} />
<div className={classes.tableWrapper}>
<Table className={classes.table} aria-labelledby="tableTitle">
<EnhancedTableHead
numSelected={selected.length}
order={order}
orderBy={orderBy}
onSelectAllClick={this.handleSelectAllClick}
onRequestSort={this.handleRequestSort}
rowCount={data.length}
/>
<TableBody>
{data
.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
.map(n => {
const isSelected = this.isSelected(n.ref);
return (
<TableRow
hover
onClick={event => this.handleRowClick(event, n.ref)}
role="checkbox"
aria-checked={isSelected}
tabIndex={-1}
key={n.ref}
selected={isSelected}
>
<TableCell padding="checkbox">
<Checkbox
checked={isSelected}
onChange={event => this.handleClick(event, n.ref)}
/>
</TableCell>
<TableCell>
<Avatar
alt={n.name}
src={`//logo.clearbit.com/${n.clearBit}`}
onError={e => {
e.target.src =
'https://doxhze3l6s7v9.cloudfront.net/app/static/img/company-default-img.png';
}}
/>
</TableCell>
<TableCell>{n.name}</TableCell>
<TableCell>{n.owner}</TableCell>
<TableCell numeric>{n.dateCreated}</TableCell>
</TableRow>
);
})}
{emptyRows > 0 && (
<TableRow style={{ height: 49 * emptyRows }}>
<TableCell colSpan={6} />
</TableRow>
)}
</TableBody>
</Table>
</div>
<TablePagination
component="div"
count={data.length}
rowsPerPage={rowsPerPage}
page={page}
backIconButtonProps={{
'aria-label': 'Previous Page'
}}
nextIconButtonProps={{
'aria-label': 'Next Page'
}}
onChangePage={this.handleChangePage}
onChangeRowsPerPage={this.handleChangeRowsPerPage}
/>
</Paper>
);
}
}
Companies.propTypes = {
classes: PropTypes.object.isRequired
};
Any insight into why the table behaves the way it does would be greatly appreciated. Thank you!
Related
I have 2 data sets that are currently being mapped over. the second data set is being mapped over inside of the first data set and rendering the values onto a modal for the user to view. I am however trying to take this second data set that is being mapped over out of its map sequence to render a sum total of each associated data point. For instance, I have a 'goalValue', an 'actualValue', and a 'result' value each of which belong to a specified category.
I should like to grab these data points when they are mapped over and push them out of the map into a separate array and or state to calculate a total that can be rendered at the bottom of the table in the modal itself. I created a separate component called ResultCalculator that takes in each value within the 'category.' Currently the state that i am trying to push the mapped values to is causing an infinite loop. I thought that maybe i could use a 'useEffect' but that isn't possible inside of a callback function.
I have added the code below for reference. Any potential insight would be greatly appreciated. I have been working on this for the last few hours whilst gaining no headway. Any search I've typed in on google has yet to render any valuable response.
Here is the code for the mappings.
const Reports = () => {
// declare const for grabbing user profile
const userProfile = () => {
axios.get('/api/users/profile', {
headers: {
'Authorization': `Bearer ${localStorage.getItem('user')}`
}
}
)
.then(res => {
console.log(res.data)
setUsers({ ...users, months: res.data.months })
})
}
// BUTTON TO DELETE A MONTH
const handleDeleteMonth = (id) => {
console.log(id)
axios.delete(`/api/months/${id}`, {
headers: {
'Authorization': `Bearer ${localStorage.getItem('user')}`
}
}).then(res => {
console.log(res)
userProfile()
})
}
//GRAB THE USER PROFILE
const [users, setUsers] = useState({ months: [] })
useEffect(() => {
userProfile()
}, [])
// defining modal styles
const style = {
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
width: 1000,
bgcolor: 'background.paper',
border: '2px solid #000',
boxShadow: 24,
p: 4,
};
// defining modal state
const [open, setOpen] = React.useState({});
const handleOpen = monthId => setOpen(prev => ({ ...prev, [monthId]: true }));
const handleClose = monthId => setOpen(prev => ({ ...prev, [monthId]: false }));
//RESULT CALCULATION STATES
const [actualsArray, setActualsArray] = useState(0)
// const [goalsResult, setGoalsResult] = useState(0)
// const [resultsResult, setResultsResult] = useState(0)
return (
<>
<NavBar></NavBar>
<br></br> <br></br>
<h1 style={{ color: "white", textAlign: "center", fontSize: "50px" }}>Budget Summaries</h1>
<br></br> <br></br>
<Container>
<Grid container spacing={2}>
<Grid item xs={0} md={1}>
</Grid>
<Grid item xs={12} md={10}>
<TableContainer component={Paper}>
<Table sx={{ minWidth: 700 }} aria-label="customized table">
<TableHead>
<TableRow>
<StyledTableCell style={{ fontSize: "25px" }}>Month</StyledTableCell>
</TableRow>
</TableHead>
<TableBody>
{users.months.map(month => (
<StyledTableRow key={month._id}>
<StyledTableCell component="th" scope="row">
<Button onClick={() => handleOpen(month._id)} align="left">{month.name}</Button>
<Button style={{ minWidth: 200 }} align="right" onClick={() => {handleDeleteMonth(month._id)}}>Delete</Button>
<Modal
open={open[month._id]}
onClose={() => handleClose(month._id)}
aria-labelledby="modal-modal-title"
aria-describedby="modal-modal-description"
>
<Box sx={style}>
<Typography id="modal-modal-title" variant="h6" component="h2">
<Container>
< Grid container spacing={2} >
<Grid item xs={0} md={1}>
</Grid>
<Grid item xs={12} md={10}>
<TableContainer component={Paper}>
<Table sx={{ minWidth: 700 }} aria-label="customized table">
<TableHead>
<TableRow>
<StyledTableCell style={{ fontSize: "25px" }}>Categories</StyledTableCell>
<StyledTableCell style={{ fontSize: "25px" }} align="right">Spent</StyledTableCell>
<StyledTableCell style={{ fontSize: "25px" }} align="right">Goals</StyledTableCell>
<StyledTableCell style={{ fontSize: "25px" }} align="right">Results</StyledTableCell>
<StyledTableCell style={{ fontSize: "25px" }} align="right"></StyledTableCell>
</TableRow>
</TableHead>
<TableBody>
{month.categories.map(category => (
<>
<StyledTableRow key={category.name}>
<StyledTableCell component="th" scope="row">
{category.name}
</StyledTableCell>
<StyledTableCell align="right">{category.actualValue}</StyledTableCell>
<StyledTableCell align="right">{category.goalValue}</StyledTableCell>
<StyledTableCell align="right">{category.result}</StyledTableCell>
<StyledTableCell align="right"></StyledTableCell>
</StyledTableRow>
</>
))}
<StyledTableRow>
<styledTableCell component="th" scope="row">Net</styledTableCell>
<StyledTableCell align="right"><ResultCalculator/></StyledTableCell>
<StyledTableCell align="right"><ResultCalculator/></StyledTableCell>
<StyledTableCell align="right"><ResultCalculator/></StyledTableCell>
<StyledTableCell align="right"></StyledTableCell>
</StyledTableRow>
</TableBody>
</Table>
</TableContainer>
</Grid>
<Grid item xs={0} md={1}>
</Grid>
</Grid >
</Container >
</Typography>
</Box>
</Modal>
</StyledTableCell>
</StyledTableRow>
))}
</TableBody>
</Table>
</TableContainer>
</Grid>
<Grid item xs={0} md={1}>
</Grid>
</Grid>
</Container>
<br></br><br></br>
<hr style={{ color: "white" }}></hr>
<Footer></Footer>
</>
)
}
I also will include the exterior component called ResultCalculator. There are some things that are commented out because I am currently just trying to get 1 value to calculate correctly before trying the other 2.
> function ResultCalculator(actualValue, goalValue, result) {
>
> const [actualsResult, setActualsResult] = useState(0)
// const [goalsResult, setGoalsResult] = useState(0)
// const [resultsResult,setResultsResult] = useState(0)
>
> let actuals = 0
// let goals = 0
// let results = 0
>
> const actualCalculator = (actualValue) => {
> actuals = actuals + actualValue }
>
> // const goalCalculator = (goalValue) => {
// goals = goals + goalValue
// return goals
// }
>
> // const resultCalculator = (result) => {
// results = results + result
// return results
// }
actualCalculator(actualValue)
>
> // goalCalculator()
// resultCalculator()
useEffect(() => {
> setActualsResult(actuals)
}, [])
>
> // setGoalsResult(goals)
// setResultsResult(results)
>
> return (
> <>
> {actualsResult}
> {/* {goalsResult}
> {resultsResult} */}
> </> )
>
> }
I want to inquire about Table Pagination in React UI Material.
Here I am trying to implement all the data from the API.
Some of the data that I have successfully implemented is from the API to the Material UI Table.
Bring up data based on request Rows Per Page
Bring up the data comes from the API that I have.
However when I try to implement Pagination, the Data doesn't appear properly from the API.
Example:
When the Component is rendered for the first time, it will display 5 data from the API. But when I tried to move to the next page, only the response from the API was successful, but not the data that appeared.
Here I divide it into several files:
Index Component
Index Container
File Index Component.
import React, { useState } from 'react'
// * Material UI
import {
Dialog,
DialogTitle,
DialogContent,
DialogContentText,
DialogActions,
Grid,
TableContainer,
Table,
TableHead,
TableRow,
TableCell,
TableBody,
TablePagination,
CssBaseline
} from '#material-ui/core'
import {
Add
} from '#material-ui/icons'
// * Core Component
import Layout from '#containers/v2/core/Layout'
import InputCategoryComponent from './Input'
import CardCore from '../../core/shared/Card'
import Controls from '../../core/shared/controls'
import { isEmpty } from '#client/libs/utils'
const columns = [
{ id: 'name', label: 'Name', minWidth: 500 },
{ id: 'Actions', label: 'Action', minWidth: 100 }
]
export default function CategoryComponent ({
page = 0,
rowsPerPage = 5,
rowsPerPageOptions = [5, 10, 15, 20, 25],
startDate = '',
endDate = '',
sortBy = 'created_at',
sortDirection = 'desc',
search = '',
totalCount = 0,
items = [],
fetch = () => {},
createPaymentCategory = () => {},
readPaymentCategory = () => {},
updatePaymentCategory = () => {},
deletePaymentCategory = () => {},
handleRowPerPage = () => {},
handlePagination = () => {}
}) {
const [isTable, setTable] = useState(true)
const [alert, setAlert] = useState(false)
const [hashed, setHashed] = useState('')
const [initialModel, setModel] = useState([])
const emptyRows = rowsPerPage - Math.min(rowsPerPage, totalCount - page * rowsPerPage)
const handleTable = (params) => {
setTable(params)
}
const handleAlertOpen = (payload) => {
setHashed(payload)
setAlert(true)
}
const handleChange = (payload) => {
if (isEmpty(payload)) {
setModel({
name: ''
})
setTable(false)
} else {
readPaymentCategory(payload).then((res) => {
setModel(res.data)
setTable(false)
})
}
}
const handleAlertClose = () => {
setAlert(false)
}
const onFinish = () => {
fetch(
page,
rowsPerPage,
startDate,
endDate,
sortBy,
sortDirection,
search
)
setTable(true)
setModel({
name: ''
})
}
const onDelete = () => {
deletePaymentCategory(hashed).then(() => {
setHashed('')
setAlert(false)
fetch(
page,
rowsPerPage,
startDate,
endDate,
sortBy,
sortDirection,
search
)
})
}
const onRowChange = (e) => {
handleRowPerPage(e.target.value)
fetch(
0,
e.target.value,
startDate,
endDate,
sortBy,
sortDirection,
search
)
}
const onPageChange = (event, newPage) => {
handlePagination(newPage)
fetch(
newPage,
rowsPerPage,
startDate,
endDate,
sortBy,
sortDirection,
search
)
}
return (
<Layout>
<CssBaseline />
{isTable && (
<Grid container>
<Grid item sm={12} md={12} lg={12}>
<CardCore
variant='info'
title='Payment Category'
>
<Grid container>
<Grid item sm={12} md={12} lg={!2}>
<Controls.Button
text='Create'
color='primary'
startIcon={<Add />}
onClick={() => handleChange()}
/>
</Grid>
</Grid>
<Grid container>
<Grid item sm={12} md={12} lg={!2}>
<TableContainer>
<Table stickyHeader aria-label='sticky table'>
<TableHead>
<TableRow>
{columns.map((column) => (
<TableCell
key={column.id}
align={column.align}
style={{ minWidth: column.minWidth }}
>
{column.label}
</TableCell>
))}
</TableRow>
</TableHead>
<TableBody>
{items.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage).map((row) => {
return (
<TableRow hover role='checkbox' tabIndex={-1} key={row.name}>
<TableCell>{row.name}</TableCell>
<TableCell align='left'>
<div>
<Controls.Button
text='Edit'
color='inherit'
onClick={() => handleChange(row.hashed_id)}
/>
<Controls.Button
text='Delete'
color='secondary'
onClick={() => handleAlertOpen(row.hashed_id)}
/>
</div>
</TableCell>
</TableRow>
)
})}
{emptyRows > 0 && (
<TableRow style={{ height: 53 * emptyRows }}>
<TableCell colSpan={6} />
</TableRow>
)}
</TableBody>
</Table>
</TableContainer>
<TablePagination
rowsPerPageOptions={rowsPerPageOptions}
component='div'
count={totalCount}
rowsPerPage={rowsPerPage}
page={page}
onChangePage={onPageChange}
onChangeRowsPerPage={onRowChange}
/>
</Grid>
</Grid>
</CardCore>
</Grid>
</Grid>
)}
<Dialog
open={alert}
onClose={handleAlertClose}
fullWidth
maxWidth='sm'
aria-labelledby='alert-dialog-title'
aria-describedby='alert-dialog-description'
>
<DialogTitle id='alert-dialog-title'>Are you sure want to delete this?</DialogTitle>
<DialogContent>
<DialogContentText id='alert-dialog-description'>
You wont be able to revert this!
</DialogContentText>
</DialogContent>
<DialogActions>
<Controls.Button
text='Disagree'
color='secondary'
onClick={handleAlertClose}
/>
<Controls.Button
text='Agree'
color='primary'
autoFocus
onClick={onDelete}
/>
</DialogActions>
</Dialog>
{!isTable && (
<InputCategoryComponent
controlTable={handleTable}
initialValues={initialModel}
callBack={onFinish}
createData={createPaymentCategory}
updateData={updatePaymentCategory}
/>
)}
</Layout>
)
}
File Index Container.
import React, { Component } from 'react'
import { mapStateToProps, mapActions } from '#client/store'
import { connect } from 'react-redux'
// * Category Component
import CategoryComponent from '#components/v2/Payment/Category/Index'
class PaymentCategoryContainer extends Component {
constructor (props) {
super(props)
this.state = {
page: 0,
rowsPerPage: 5,
rowsPerPageOptions: [5, 10, 15, 20, 25],
startDate: '',
endDate: '',
sortBy: 'created_at',
sortDirection: 'desc',
search: '',
totalCount: 0,
items: []
}
this.fetch = this.fetch.bind(this)
this.handleRow = this.handleRow.bind(this)
this.handlePage = this.handlePage.bind(this)
}
fetch (page, rowsPerPage, startDate, endDate, sortBy, sortDirection, search) {
this.props.fetchPaymentCategory(
page,
rowsPerPage,
startDate,
endDate,
sortBy,
sortDirection,
search
).then((res) => {
if (res?.status === 200) {
this.setState({
items: res?.data.items,
totalCount: res?.data.totalItems
})
} else {
console.log('error')
}
})
}
handleRow (rowsPerPage) {
this.setState({
rowsPerPage: rowsPerPage
})
const { page, startDate, endDate, sortBy, sortDirection, search } = this.state
this.fetch(
page,
rowsPerPage,
startDate,
endDate,
sortBy,
sortDirection,
search
)
}
handlePage (numberOfPage) {
this.setState({
page: numberOfPage
})
const { rowsPerPage, startDate, endDate, sortBy, sortDirection, search } = this.state
this.fetch(
numberOfPage,
rowsPerPage,
startDate,
endDate,
sortBy,
sortDirection,
search
)
}
componentDidMount () {
this.fetch(
this.state.page,
this.state.rowsPerPage,
'',
'',
this.state.sortBy,
this.state.sortDirection,
''
)
}
render () {
return (
<CategoryComponent
{...this.props}
{...this.state}
fetch={this.fetch}
handleRowPerPage={this.handleRow}
handlePagination={this.handlePage}
/>
)
}
}
export default connect(
mapStateToProps('paymentCategory'),
mapActions(
'fetchPaymentCategory',
'changeRowPerPage',
'changePagination',
'createPaymentCategory',
'readPaymentCategory',
'updatePaymentCategory',
'deletePaymentCategory'
)
)(PaymentCategoryContainer)
Response data from API:
items: [] => array. totalItems: 0 => int
Are there any mistakes that I missed? or is there a step that i missed ?.
I am following the examples in this section ui material.
Thank you.
I have found where the mistake I made. I shouldn't need to slice() the data. Because I have a params page query so I just need to map() something like this.
return (
<Layout>
<CssBaseline />
{isTable && (
<Grid container>
<Grid item sm={12} md={12} lg={12}>
<CardCore
variant='info'
title='Payment Category'
>
<Grid container>
<Grid item sm={12} md={12} lg={!2}>
<Controls.Button
text='Create'
color='primary'
startIcon={<Add />}
onClick={() => handleChange()}
/>
</Grid>
</Grid>
<Grid container>
<Grid item sm={12} md={12} lg={!2}>
<TableContainer>
<Table stickyHeader aria-label='sticky table'>
<TableHead>
<TableRow>
{columns.map((column) => (
<TableCell
key={column.id}
align={column.align}
style={{ minWidth: column.minWidth }}
>
{column.label}
</TableCell>
))}
</TableRow>
</TableHead>
<TableBody>
{items.map((row) => {
return (
<TableRow hover role='checkbox' tabIndex={-1} key={row.name}>
<TableCell>{row.name}</TableCell>
<TableCell align='left'>
<div>
<Controls.Button
text='Edit'
color='inherit'
onClick={() => handleChange(row.hashed_id)}
/>
<Controls.Button
text='Delete'
color='secondary'
onClick={() => handleAlertOpen(row.hashed_id)}
/>
</div>
</TableCell>
</TableRow>
)
})}
{emptyRows > 0 && (
<TableRow style={{ height: 53 * emptyRows }}>
<TableCell colSpan={6} />
</TableRow>
)}
</TableBody>
</Table>
</TableContainer>
<TablePagination
rowsPerPageOptions={rowsPerPageOptions}
component='div'
count={totalCount}
rowsPerPage={rowsPerPage}
page={page}
onChangePage={onPageChange}
onChangeRowsPerPage={onRowChange}
/>
</Grid>
</Grid>
</CardCore>
</Grid>
</Grid>
)}
<Dialog
open={alert}
onClose={handleAlertClose}
fullWidth
maxWidth='sm'
aria-labelledby='alert-dialog-title'
aria-describedby='alert-dialog-description'
>
<DialogTitle id='alert-dialog-title'>Are you sure want to delete this?</DialogTitle>
<DialogContent>
<DialogContentText id='alert-dialog-description'>
You wont be able to revert this!
</DialogContentText>
</DialogContent>
<DialogActions>
<Controls.Button
text='Disagree'
color='secondary'
onClick={handleAlertClose}
/>
<Controls.Button
text='Agree'
color='primary'
autoFocus
onClick={onDelete}
/>
</DialogActions>
</Dialog>
{!isTable && (
<InputCategoryComponent
controlTable={handleTable}
initialValues={initialModel}
callBack={onFinish}
createData={createPaymentCategory}
updateData={updatePaymentCategory}
/>
)}
</Layout>
)
}
Hope this helps others.
I'm a bit lost on this.
I already try many settings with scrollTop.
Let me explain, I'm using material Ui and their pagination stuff with table documentation here
so I'm stuck when I click on next set of row( or change page ), I start at the bottom. but I would like to start at the top of every new row.
If someone can help me and give me an explanation of why, A huge thanks!
sorry, I'm quite new to React.
here is my code :
function DisplayList(props) {
var rows = [];
const data = props.data;
const searchData = props.searchData;
const setHoverAddress = props.setHoverAddress;
const classes = useStyles1();
const [page, setPage] = useState(0);
const [rowsPerPage, setRowsPerPage] = useState(5);
const handleChangePage = (event, newPage) => {
setPage(newPage);
};
const handleChangeRowsPerPage = (event) => {
setRowsPerPage(parseInt(event.target.value, 10));
setPage(0);
};
data.map((result, index) => { // WARNING : slice here which limits the number of results: .slice(0, 5)
const volulme = Math.round(result.volulme);
const volulme2 = Math.round(result.volulme2);
rows.push(
<div id={index}>
<ListItem
alignItems="flex-start"
onMouseEnter={e => {
console.log(index);
}}
>
<Grid container direction="row" spacing={1}>
<Grid item xs={5}>
{/* <Stage width={150} height={150}>
<Layer>
<Shape
sceneFunc={(context, shape) => {
context.beginPath();
context.moveTo(20, 10);
context.lineTo(120, 80);
context.lineTo(120, 140);
context.lineTo(22, 140);
context.closePath();
// (!) Konva specific method, it is very important
context.fillStrokeShape(shape);
}}
fill="#00D2FF"
stroke="black"
strokeWidth={2}
/>
</Layer>
</Stage> */}
</Grid>
<Grid item xs={7}>
<ListItemText
primary={
}
secondary={
<React.Fragment>
<Typography
component="span"
variant="body2"
display="inline"
color="textPrimary"
>
Solid2 : {volulme2}
</Typography>
</React.Fragment>
}
/>
<ListItemText
secondary={
<React.Fragment>
<Typography
component="span"
variant="body2"
display="inline"
color="textPrimary"
>
Solid : {volulme}
</Typography>
</React.Fragment>
}
/>
<FormControlLabel
control={
<Checkbox icon={<FavoriteBorder />}
checkedIcon={<Favorite />}
color="primary"
onClick={(e) => {
if (e.target.checked) {
addFavourite(parc_id, 1)
} else {
removeFavourite(parc_id, 1)
}
}}
name="checkedH" />
}
label="Enregistrer"
/>
</Grid>
</Grid>
</ListItem>
</div>
)
})
return (
<Table className={classes.table} aria-label="custom pagination table">
<TableBody>
{(rowsPerPage > 0
? rows.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
: rows
).map((row) => (
<TableRow key={index}>
<TableCell component="th" scope="row">
{row}
</TableCell>
</TableRow>
))}
</TableBody>
<TableFooter>
<TableRow>
<TablePagination
rowsPerPageOptions={[5, 10, 25, { label: 'All', value: -1 }]}
colSpan={3}
count={rows.length}
rowsPerPage={rowsPerPage}
page={page}
SelectProps={{
inputProps: { 'aria-label': 'rows per page' },
native: true,
}}
onChangePage={handleChangePage}
onChangeRowsPerPage={handleChangeRowsPerPage}
ActionsComponent={TablePaginationActions}
/>
</TableRow>
</TableFooter>
</Table>
)
}
Have you tried scrollIntoView?
I used scrollTo not working but scrollIntoView is fine.
const handleChangeRowsPerPage = (event) => {
tableRef.current && tableRef.current.scrollIntoView();
setRowsPerPage(parseInt(event.target.value, 10))
setPage(0)
}
I don't see scrollTop in your example, so it's tough to say exactly what the issue is. If you just trying to scroll the window try window.scrollTo(0, 0);
https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollTo
If your trying to scroll the table element itself you can use a ref.
To the top of your component add:
function DisplayList(props) {
const tableRef = React.createRef();
var rows = [];
const data = props.data;
...
Add the ref to your table:
return (
<Table
ref={tableRef}
className={classes.table}
aria-label="custom pagination table"
>
<TableBody>
...
Finally your page event use the ref to change scrollTop
const handleChangePage = (event, newPage) => {
setPage(newPage);
tableRef.current?.scrollTop = 0;
};
Оn Angular Material i did like this
// html
<table mat-table [dataSource]="dataSource" #dataTable>
...
</table>
// ts
#ViewChild('dataTable') dataTable: ElementRef;
pageChange(event: { pageSize: number; pageIndex: number; }): void {
const tableElement = this.dataTable['_elementRef']?.nativeElement;
tableElement?.scrollIntoView();
// set current page event.pageIndex or event.pageIndex + 1
// get data
}
I am trying to get page data which is coming from redux store and pass this to local state named pagination. This pagination state is further passed to child component. But the Problem is whenever i try to pass redux state to local state i get error undefined. Here data is defined I can console.log the data but it gets delayed that why i might be getting the error. I don't know how to solve this. I am using react functional component.
newOrder.js
const [pagination, setPagination] = React.useState({});
const DataReceived = (state) =>
state.OrderAndShipping.NewOrderList.newOrder._embedded;
const selectedData = useSelector(DataReceived, shallowEqual);
const NewOrder = selectedData ? selectedData.customerOrderResourceList : null;
const pageState = (state) =>
state.OrderAndShipping.NewOrderList.newOrder.page;
const selectPage = useSelector(pageState);
console.log("page", selectPage);
React.useEffect(() => {
const access_token = localStorage.getItem("access_token");
props.getNewOrderList(access_token, "", ""); <-- redux dispatch function
}, []);
React.useEffect(() => {
setPagination(selectPage); <-- Here i am trying to pass redux state to localstate.
}, []);
const mapStateProps = (state) => {
console.log(state);
return {
newOrder: state.OrderAndShipping.NewOrderList.newOrder
? state.OrderAndShipping.NewOrderList.newOrder._embedded
: null,
};
};
const mapDispatchToProps = {
getNewOrderList, <-- Dispatching function
};
Passing
{TableData && TableData.rows && TableData.rows.length > 0 && (
<Table
_handleCheckbox={_handleCheckbox}
_handlePagination={_handlePagination}
_handleUserCheckBox={_handleUserCheckBox}
data={TableData}
pagination={pagination}
/>
)}
Table.js
const emptyRows =
rowsPerPage -
Math.min(
rowsPerPage,
props.data.rows.length - props.pagination.number * rowsPerPage
);
const { number } = props.pagination;
return (
<div className={classes.root}>
<Paper className={classes.paper}>
<EnhancedTableToolbar numSelected={selected.length} data={props.data} />
<div className={classes.tableWrapper}>
<Table
className={classes.table}
aria-labelledby="tableTitle"
size={dense ? "small" : "medium"}
>
{/*//! Table Head Component */}
<EnhancedTableHead
numSelected={selected.length}
order={order}
orderBy={orderBy}
onSelectAllClick={handleSelectAllClick}
onRequestSort={handleRequestSort}
rowCount={props.data.rows.length}
data={props.data}
/>
{/*//! Table Body Component */}
<TableBody>
{stableSort(props.data.rows, getSorting(order, orderBy))
.slice(number * rowsPerPage, number * rowsPerPage + rowsPerPage)
.map((row, index) => {
const isItemSelected = isSelected(row.name);
const labelId = `enhanced-table-checkbox-${index}`;
return (
<TableRow
hover
onClick={(event) =>
handleClick(event, row.name, row.userId)
}
role="checkbox"
aria-checked={isItemSelected}
tabIndex={-1}
key={props.data.rows.name}
selected={isItemSelected}
>
</TableRow>
);
})}
{emptyRows > 0 && (
<TableRow style={{ height: 49 * emptyRows }}>
<TableCell colSpan={6} />
</TableRow>
)}
</TableBody>
</Table>
</div>
{/**
* ===============================================
* PAGINATION
* =============================================
*/}
<TablePagination
rowsPerPageOptions={[5, 10, 25]}
component="div"
count={props.data.rows.length}
rowsPerPage={rowsPerPage}
page={props.pagination.number}
backIconButtonProps={{
"aria-label": "Previous Page",
}}
nextIconButtonProps={{
"aria-label": "Next Page",
}}
onChangePage={props._handlePagination}
onChangeRowsPerPage={handleChangeRowsPerPage}
/>
</Paper>
console.log pagination
console.log("page", selectPage);
Table.js
function EnhancedTable(props) {
const [rowsPerPage, setRowsPerPage] = React.useState(10);
//! Select All Checkbox
function handleSelectAllClick(event) {
if (event.target.checked) {
const newSelecteds = props.data.rows.map((n) => n.name);
setSelected(newSelecteds);
return;
}
setSelected([]);
}
//! Handle CheckBox here
function handleClick(event, name, userId) {
const selectedIndex = selected.indexOf(name);
let newSelected = [];
const selectedIdIndex = SelectedId.indexOf(userId);
let newSelectedIndex = [];
console.log(userId);
let userid = [];
userid = userId;
console.log(selectedIndex);
props._handleCheckbox(selectedIdIndex, userid, SelectedId);
function handleChangeDense(event) {
setDense(event.target.checked);
}
const isSelected = (name) => selected.indexOf(name) !== -1;
const emptyRows =
rowsPerPage -
Math.min(
rowsPerPage,
props.data.rows.length - props.pagination.number * rowsPerPage
);
const { number } = props.pagination;
return (
<div className={classes.root}>
<Paper className={classes.paper}>
<EnhancedTableToolbar numSelected={selected.length} data={props.data} />
<div className={classes.tableWrapper}>
<Table
className={classes.table}
aria-labelledby="tableTitle"
size={dense ? "small" : "medium"}
>
<EnhancedTableHead
numSelected={selected.length}
order={order}
orderBy={orderBy}
onSelectAllClick={handleSelectAllClick}
onRequestSort={handleRequestSort}
rowCount={props.data.rows.length}
data={props.data}
/>
{/*//! Table Body Component */}
<TableBody>
{stableSort(props.data.rows, getSorting(order, orderBy))
.slice(number * rowsPerPage, number * rowsPerPage + rowsPerPage)
.map((row, index) => {
const isItemSelected = isSelected(row.name);
const labelId = `enhanced-table-checkbox-${index}`;
return (
<TableRow
hover
onClick={(event) =>
handleClick(event, row.name, row.userId)
}
role="checkbox"
aria-checked={isItemSelected}
tabIndex={-1}
key={props.data.rows.name}
selected={isItemSelected}
>
<TableCell padding="checkbox">
<Checkbox
checked={isItemSelected}
inputProps={{ "aria-labelledby": labelId }}
/>
</TableCell>
{rowData(row)}
</TableRow>
);
})}
{emptyRows > 0 && (
<TableRow style={{ height: 49 * emptyRows }}>
<TableCell colSpan={6} />
</TableRow>
)}
</TableBody>
</Table>
</div>
{/**
* ===============================================
* PAGINATION
* =============================================
*/}
<TablePagination
rowsPerPageOptions={[5, 10, 25]}
component="div"
count={props.data.rows.length}
rowsPerPage={rowsPerPage}
page={props.pagination.number}
backIconButtonProps={{
"aria-label": "Previous Page",
}}
nextIconButtonProps={{
"aria-label": "Next Page",
}}
onChangePage={() => props.handlePagination()}
onChangeRowsPerPage={handleChangeRowsPerPage}
/>
</Paper>
</div>
);
}
const mapStateToProps = (state) => {
return {
checkbox: state.AllUsers.Admin.checkBox,
};
};
export default connect(mapStateToProps, {})(EnhancedTable);
Issue :
As per your console log you are getting selectPage undefined initially, and you also setting up the value only on mount
React.useEffect(() => {
setPagination(selectPage); <-- Here i am trying to pass redux state to localstate.
}, []); // <--- this will executed only on mount
Solution :
I think you should listen for the changes in selectPage and only update If it's available
React.useEffect(() => {
if(selectPage) { // <--- check if available
setPagination(selectPage);
}
}, [selectPage]); // <--- will run useEffect on everychange of `selectPage`
Hello below I have a class that doesn't use any life-cycle methods or states, I have read documentation about converting such classes into consts. however, I'm not sure how I seem to struggle with the below class:
class ContractsTableHead extends Component {
createSortHandler(property) {
return event => {
this.props.onRequestSort(event, property);
};
}
render() {
const { order, orderBy } = this.props;
return (
<TableHead>
<TableRow>
{rows.map(
row => (
<TableCell
key={row.id}
align={row.numeric ? "right" : "left"}
padding={row.disablePadding ? "none" : "default"}
sortDirection={orderBy === row.id ? order : false}
>
<Tooltip
title="Sort"
placement={row.numeric ? "bottom-end" : "bottom-start"}
enterDelay={300}
>
<TableSortLabel
active={orderBy === row.id}
direction={order}
onClick={this.createSortHandler(row.id)}
>
{row.label}
</TableSortLabel>
</Tooltip>
</TableCell>
),
this
)}
</TableRow>
</TableHead>
);
}
}
ContractsTableHead.propTypes = {
onRequestSort: PropTypes.func.isRequired,
order: PropTypes.string.isRequired,
orderBy: PropTypes.string.isRequired,
rowCount: PropTypes.number.isRequired
};
export default ContractsTableHead;
If you make the class component into a function component, you need to make your method createSortHandler into a regular function as well:
const ContractsTableHead = props => {
const createSortHandler = property => {
return event => {
props.onRequestSort(event, property);
};
};
const { order, orderBy } = props;
return (
<TableHead>
<TableRow>
{rows.map(row => (
<TableCell
key={row.id}
align={row.numeric ? "right" : "left"}
padding={row.disablePadding ? "none" : "default"}
sortDirection={orderBy === row.id ? order : false}
>
<Tooltip
title="Sort"
placement={row.numeric ? "bottom-end" : "bottom-start"}
enterDelay={300}
>
<TableSortLabel
active={orderBy === row.id}
direction={order}
onClick={createSortHandler(row.id)}
>
{row.label}
</TableSortLabel>
</Tooltip>
</TableCell>
))}
</TableRow>
</TableHead>
);
};