How to override MTablePagination from material-table reactjs? - reactjs

I have more than one million rows and want to display them in material-table reactjs. How do I get data from back-end only for rows on one page and then get next set of rows on next page click?
import React, { useState, useEffect } from 'react';
import MaterialTable from 'material-table';
import Axios from 'axios'
export default function MaterialTableDemo() {
var columns = [
{title: "stationid", field: "stationid", editable: 'never'},
{title: "model", field: "model", editable: 'never'},
{title: "version", field: "version", editable: 'never'},
{title: "lat", field: "lat", editable: 'never'},
{title: "lon", field: "lon", editable: 'never'},
{title: "status", field: "status"}
]
const [data, setData] = useState([]);
useEffect(() => {
Axios.get("/ListView")
.then(res => {
setData(res.data.data)
console.log(res.data.data)
})
.catch(error=>{
console.log("Error")
})
}, [])
const handleRowUpdate = (newData, oldData, resolve) => {console.log("updating row")
let errorList = []
if(newData.status === ""){
errorList.push("Please enter Status")
}
if(errorList.length < 1){
Axios.post("/update", newData)
.then(res => {
const dataUpdate = [...data];
const index = oldData.tableData;
dataUpdate[index] = newData;
setData([...dataUpdate]);
resolve()}
)
.catch(error => {
resolve()
})
}else{
resolve()
}
window.location.reload(true);
}
const handleRowDelete = (oldData, resolve) => {
Axios.post("/delete", oldData)
.then(res => {
const dataDelete = [...data];
const index = oldData.tableData;
dataDelete.splice(index, 1);
setData([...dataDelete]);
resolve()
})
.catch(error => {
resolve()
})
window.location.reload(true);
}
return (
<MaterialTable
title="Station MetaData from DB"
columns={columns}
data={data}
options={{
exportButton: true,
showFirstLastPageButtons: false,
}}
localization={{
pagination: {
labelDisplayedRows: '{from}-{to}'
},
}}
editable={{
onRowUpdate: (newData, oldData) =>
new Promise((resolve) => {
handleRowUpdate(newData, oldData, resolve);
}),
onRowDelete: (oldData) =>
new Promise((resolve) => {
handleRowDelete(oldData, resolve)
}),
}}
/>
);
}
How do I make get only as many rows from backend as possible on 1 page for display? For example, if I want to display only 5 rows per page then I should get only 5 rows from backend and on click on next page get next 5 rows.

I know its a bit late but maybe it will help others with the same question.
You should override Pagination in components:
<MaterialTable
options={options}
data={data}
columns={columns}
editable={{onRowUpdate}}
localization={localization}
components={{
Pagination: (props) =>
<CustomPagination
props={props}
rowsPerPage={pageSize}
pageIndex={pageIndex}
setPageIndex={setPageIndex}
setPageSize={setPageSize}/>
}
}}
/>
where
<CustomPagination
rowsPerPageOptions={rowsPerPageOptions}
rowsPerPage={rowsPerPage}
count={totalPages}
page={pageIndex}
onChangePage={(event, page) => {
props.onChangePage(event, page);
setPageIndex(page)
}}
onChangeRowsPerPage={event => {
props.onChangeRowsPerPage(event);
setPageSize(parseInt(event.target.value));
}}
/>
All the fields in CustomPagination are hooks from it's parent component so that you will do your api calls and re-render when they change .
Using the same way you can change the text of this buttons, please check this example https://material-table.com/#/docs/features/localization.

Related

ReactTable component is not rendering data coming from api,If i use hardcoded data it is showing

I am using reacttable-6 to render the data in table,but the is not showing up in table.It is giving me "No data found".Data is coming from api,even i console logged the response from api,the what data i am getting from is fine.I aslo hard coded the data,then the data is showing up in the table
I am not able to figure out what the issue is.Thanks inadvance.
import React,{useState} from 'react'
import ReactTable from "react-table-6";
import 'react-table-6/react-table.css';
import axios from "axios";
export default function Inventory(){
var compdata = [
{
FirstName: "Chandu",
LastName: "Reddy",
_id: "63c5766f9d9de1b624481574",
Discription: {
_id: "63c5766f9d9de1b624481574",
DOB: "Havells",
Age: "HiBreak",
},
Address: "Something",
}
];
const handleDelete=(data)=>{
console.log(data)
}
const handleEdit=()=>{
console.log("dcdc")
}
const column = [
{
Header: "FirstName",
accessor: "FirstName",
sortable: false
},
{
Header: "LastName",
accessor: "LastName",
sortable: false
},
{
Header: "Address",
accessor: "Address",
sortable: false
},
{
Header: "Actions",
Cell: (row) => (
<div>
<a onClick={() => handleEdit(row.original)}>
Edit
</a>
<a onClick={() => handleDelete(row.original)}>
Delete
</a>
</div>
)
}
];
const [data1, setData1] = useState([]);
const [columns, setColumns] = useState(column);
const { toggle } = useContext(ThemeContext);
useEffect(()=>{
const fetch = async () => {
await axios
.get(`http://localhost:4001/api/uploadCsv/getData`)
.then((res) => {
setData1(res.data);
console.log(res.data)
});
};
fetch();
},[setData1]);
const [expanded, setExpanded] = useState({});
const onExpandedChange = (newExpanded) => {
setExpanded(newExpanded);
};
return(
<div className="container">
<div className='Table-container'>
<ReactTable
data={data1}
columns={columns}
defaultPageSize={data1.length}
showPagination={false}
resizable={false}
expanded={expanded}
// className="-striped -highlight"
getTrProps={(state, rowInfo, column, instance, expanded) => {
return rowInfo
? {
onClick: (expanded) => {
const newExpanded = { ...expanded };
newExpanded[rowInfo.viewIndex] = expanded[rowInfo.viewIndex]
? false
: true;
setExpanded(newExpanded);
}
}
: {};
}}
SubComponent={(row) => {
return (
<div style={{ padding: "20px" }}>
<em>{(row.original.Discription.Make)}</em>K <br />
</div>
);
}}
/>
<br />
</div>
</div>
)
}
Screen shot for reference
Change your useEffect like this and add another to check did data1 updated yet. Depend on data1 have value or not we will have different way to solve this
useEffect(() => {
axios.get(`http://localhost:4001/api/uploadCsv/getData`).then((res) => {
setData1(res.data);
});
}, []);
useEffect(()=>{
console.log(data1)
},[data1])

Ant design Transform component extracting selected data

I need to extract selected/filtered data into the state. I tried everything with onChange and on select change but only I got is the ID of one specific item.
ex. extracted_data = [ '1','2','3'....]
But I need a complete Item with id, name, price, etc...
I am passing data as source data, and after selecting I want to send in the parent component because I need to send it on the server.
Code is below
import { Table, Transfer } from "antd";
import difference from "lodash/difference";
import React, { useState } from "react";
// Customize Table Transfer
const TableTransfer = ({ leftColumns, rightColumns, ...restProps }) => (
<Transfer {...restProps}>
{({
direction,
filteredItems,
onItemSelectAll,
onItemSelect,
selectedKeys: listSelectedKeys,
disabled: listDisabled,
}) => {
const columns = direction === "left" ? leftColumns : rightColumns;
const rowSelection = {
getCheckboxProps: (item) => ({
disabled: listDisabled || item.disabled,
}),
onSelectAll(selected, selectedRows) {
const treeSelectedKeys = selectedRows
.filter((item) => !item.disabled)
.map(({ key }) => key);
const diffKeys = selected
? difference(treeSelectedKeys, listSelectedKeys)
: difference(listSelectedKeys, treeSelectedKeys);
onItemSelectAll(diffKeys, selected);
},
onSelect({ key }, selected) {
onItemSelect(key, selected);
},
selectedRowKeys: listSelectedKeys,
};
return (
<Table
rowSelection={rowSelection}
columns={columns}
dataSource={filteredItems}
size="small"
style={{
pointerEvents: listDisabled ? "none" : undefined,
}}
onRow={({ key, disabled: itemDisabled }) => ({
onClick: () => {
if (itemDisabled || listDisabled) return;
onItemSelect(key, !listSelectedKeys.includes(key));
},
})}
/>
);
}}
</Transfer>
);
const leftTableColumns = [
{
dataIndex: "name",
title: "Name",
},
{
dataIndex: "price",
title: "Price (€)",
},
{
dataIndex: "discount",
title: "Discount (%)",
},
];
const rightTableColumns = [
{
dataIndex: "name",
title: "Name",
},
{
dataIndex: "price",
title: "Price",
},
];
const App = ({ data, func }) => {
const mockData = data.map((item) => ({
key: item.id.toString(),
name: item.name,
price: item.price,
discount: item.discount,
}));
const originTargetKeys = mockData.map((item) => item.key);
const [targetKeys, setTargetKeys] = useState(originTargetKeys);
const [selected, setSelected] = useState([]);
const onSelectChange = (e) => {
setSelected(e);
};
const onChange = (e) => {
setTargetKeys(e);
func(selected);
};
return (
<>
<TableTransfer
dataSource={mockData}
targetKeys={targetKeys}
disabled={false}
showSearch={true}
onChange={onChange}
onSelectChange={onSelectChange}
filterOption={(inputValue, item) =>
item.name.indexOf(inputValue) !== -1
}
leftColumns={leftTableColumns}
rightColumns={rightTableColumns}
/>
</>
);
};
export default App;

Updating Graph on Interval on React

I am getting data from my database to display it on the graph. Currently, I will have to refresh the page for the graph to update. I would like to refresh the graph in x interval as my data will be inserted at x interval. Am using ant design for the graph plotting. I am using a 'home' to display my graph and another class for my data fetching.
Home.js
export class Home extends Component {
static displayName = Home.name;
render () {
return (
<div>
<h1>Dashboard</h1>
<h2>
<div className="site-card-wrapper">
Graph1
<Graph />}
</div>
</h2>
</div>
);
}
}
Temp.js
const TempGraph = () => {
const [data, setData] = useState([]);
useEffect(() => {
asyncFetch();
}, []);
const asyncFetch = () => {
fetch('link')
.then((response) => response.json())
.then((json) => setDatajson))
.catch((error) => {
console.log('fetch data failed', error);
});
};
const config = {
data,
xField: 'time',
yField: 'value',
seriesField:'location',
xAxis: {
title: {
text: 'Hours',
}
},
yAxis:{
title:{
text: 'Temperature in °',
}
},
meta: {
time: {
alias: 'hours',
},
value: {
alias: 'temperature',
max: 50,
},
},
};
return <Line {...config} />;
}
export default TempGraph;
You could just add a setInterval in your useEffect to grab the data and update them again. Don't forgot to clear the interval on return:
useEffect(() => {
const interval = setInterval(() => asyncFetch(), 5000)
return () => clearInterval(interval)
}, []}
This example triggers every 5000ms, change the value according to your needs.

Increase width of select lookup box in React Material-Table

I am using Material-Table in React and trying to increase the width of this 'lookup' column in 'Requirement' field. I have tried cellStyle: {columnWidth: 800}. Also, tried width, padding. None seem to accomplish this. I've checked through the documentation, and a few other places, but not able to resolve this. Appreciate anyone who knows how to make this change.
enter code here
const [columns] = useState([
{ title: 'Skills', field: 'type' },
{ cellStyle: {columnWidth: 800}, title: 'Requirement', field: 'mustHave', lookup: {34: 'Required', 63: 'Must-have'} /*initialEditValue: 'initial edit value'*/ },
{ cellStyle: {textAlign: 'left'}, headerStyle: {textAlign: 'left'}, title: 'Desired Rating', field: 'desiredRating',
editComponent: (props) => (
<Input
defaultValue={props.value}
onChange={(e) => props.onChange(e.target.value)}
type="number"
min="0"
max="10"
onInput={maxLengthCheck}
/>
)
}
]);
const [data, setData] = useState([]);
useEffect(() => {
setData(workExp);
}, [workExp]);
console.log(workExp);
return (
<MaterialTable
style={{fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif', fontSize: '0.875rem', textAlign: 'left'}}
title="Hiring Criteria"
columns={columns}
options={{actionsColumnIndex: -1}}
data={data}
editable={{
onRowAdd: newData =>
new Promise((resolve, reject) => {
setTimeout(() => {
setData([...data, newData]);
resolve();
}, 1000)
}),
onRowUpdate: async (newData, oldData) => {
try {
const index = oldData.tableData.id;
let newWorkExp = [...workExp];
newWorkExp[index] = newData;
console.log(data);
console.log(newWorkExp[index].mustHave === '63');
if(newWorkExp[index].mustHave === '63' || newWorkExp[index].mustHave === 'Must-have') {
newWorkExp[index].mustHave = 'Must-have';
}
console.log(newWorkExp);
setData(newWorkExp);
await dispatch(updateRequisition(id, {workExp: newWorkExp}));
await wait(1000);
} catch (err) {
console.error(err);
}
},
onRowDelete: oldData =>
new Promise((resolve, reject) => {
setTimeout(() => {
const dataDelete = [...data];
const index = oldData.tableData.id;
dataDelete.splice(index, 1);
setData([...dataDelete]);
resolve()
}, 1000)
}),
}}
/>
)
}
export default HiringCriteria;
Was able to resolve this. Used browser tools to get class name and created stylesheet using !important to override styles.

Material-Table with React: how to use star rating in the cell?

I would like to style my cell's rating into star by using Material-Table,
like the original Material-UI provided:
https://material-ui.com/components/rating/
Is it possible to use in Material-Table? I cannot find document related to this...just for the style for background, color, etc., not for writing functions in cell style.
https://material-table.com/#/docs/features/styling
thanks a lot!
You can use material-table's custom edit component to render the mui Rating component.
Full Working demo
Sample code snippet of columns array
const columns = propValue => [
{ title: "Id", field: "id" },
{ title: "First Name", field: "first_name" },
{
title: "Rating",
field: "rating",
render: rowData => {
return <Rating name="hover-feedback" value={rowData.rating} readOnly />;
},
editComponent: props => (
<Rating
name="hover-feedback"
value={props.value}
onChange={(event, newValue) => {
props.onChange(newValue);
}}
/>
),
cellStyle: {
backgroundColor: "#039be5",
color: "#FFF"
},
width: "30%"
}
];
Component
class App extends Component {
tableRef = React.createRef();
propValue = true;
state = { data: [] };
componentDidMount() {
const query = 0;
let url = "https://reqres.in/api/users?";
url += "per_page=" + query.pageSize;
url += "&page=" + (query.page + 1);
fetch(url)
.then(response => response.json())
.then(result => {
console.log("result", result);
this.setState({
data: result.data.map(d => ({ ...d }))
});
});
}
render() {
return (
<div style={{ maxWidth: "100%" }}>
<MaterialTable
icons={tableIcons}
tableRef={this.tableRef}
columns={columns(this.propValue)}
editable={{
onRowUpdate: (newData, oldData) =>
new Promise((resolve, reject) => {
console.log("newData", newData);
console.log("oldData", oldData);
const dataUpdate = [...this.state.data];
const index = oldData.tableData.id;
dataUpdate[index] = newData;
this.setState({ data: dataUpdate }, () => {
console.log("xx", this.state.data);
resolve(this.state);
});
})
}}
data={this.state.data}
title="Remote Data Example"
options={{ tableLayout: "fixed" }}
/>
<button
onClick={() => {
this.tableRef.current.onQueryChange();
}}
>
ok
</button>
</div>
);
}
}

Resources