https://ant.design/components/table/
I want to convert numbers to money using Table antd In line with this example I'm so confused, please help me, I hurry because I have to submit the last project before I graduate.
const timeConverter = rawDate => moment(rawDate).tz("Thai/Bangkok").format('L');
const { pagination } = this.props;
const columns = [
{
title: "ID",
dataIndex: "id",
align: "center",
width: "60px",
height: "30px",
},
{
title:"วันที่บันทึก",
dataIndex:"createdAt",
align:"center",
width:"200",
format:"0,0",
render: createdAt => timeConverter(createdAt)
},
{
title:"อ้างอิงใบเสร็จเลขที่ ",
dataIndex:"re_reference",
align:"center",
width:"200"
},
{
title:"ชื่อบริการ/สินค้า",
dataIndex:"re_pro_name",
align:"center",
width:"350",
},
{
title:"รายละเอียด",
dataIndex:"re_detail",
align:"center",
width:"100",
},
{
title:"รหัสสมาชิก (ถ้ามี)",
dataIndex:"re_cus_name",
align:"center",
width:"200",
},
{
title:"ประเภทรับ-จ่าย",
dataIndex:"re_type",
align:"center",
width:"350",
},
{
title:"ราคาต่อหน่วย",
dataIndex:"re_price",
align:"center",
width:"300",
// render: re_price => numeral('$0,0.00')(re_price)
render:(text, record) => (
<span> </span>
)
},
render: value => ${value}.00.replace(/\B(?=(\d{3})+(?!\d))/g, ',') //convert number monney
Related
I want to add a new row at the end of rc-table to show total of column value.
const columns = [
{
title: "Name",
className: "cursor-pointer",
dataIndex: "name",
key: "name",
Footer: "Total",
align: alignLeft,
// onHeaderCell: () => onHeaderClick('name'),
render: (name: any) => <span className="whitespace-nowrap">{name}</span>,
},
];
try this:
const columns = [
{
title: "Name",
className: "cursor-pointer",
dataIndex: "name",
key: "name",
align: alignLeft,
render: (name: any) => <span className="whitespace-nowrap">{name}</span>,
footer: (data: any) => {
let total = 0;
data.forEach((item: any) => {
total += item.name;
});
return <div>{`Total: ${total}`}</div>;
},
},
];
I am using antd to create a table with filter feature,
but I got a problem, I want to custom filter search of antd to call api,
antd table
How can I do that with react and antd,
Here is my code
const columns: ColumnsType<Product> = [
{
title: 'Name',
dataIndex: 'name',
key: 'name',
render: (name, record) => (
<div className="flex items-center">
<Avatar src={record.avatar}>{name[0].toUpperCase()}</Avatar>
<span style={{ marginLeft: 10 }} className="whitespace-nowrap">
<a title="View & Edit" href={'/product/' + record.id}>
{name}
</a>
</span>
</div>
),
},
{
title: 'About',
dataIndex: 'about',
key: 'about',
render: (about: string) => <p className="text-ellipsis line-clamp-2">{about}</p>,
width: 400,
},
{
title: 'Categories',
dataIndex: 'categories',
key: 'categories',
filterSearch: true,
filters: categories!.map((category: Category) => ({ text: category.name, value: category.id })),
render: (categories: any) => {
console.log(categories);
return '-';
},
// width: 400,
},
{ title: 'Addresses', dataIndex: 'contract_addresses', key: 'address', render: addresses => addresses?.[0] },
];
To filter the table, I usually provide a function that filters the data before it is passed to the table (In my example the function getData. This function can also be used to adjust the filter accordingly. Here is an example, which also consists of a Search-Input to modify the search:
const CustomersTable = (props: any) => {
const [searchText, setSearchText] = useState<string | undefined>(undefined);
const [customers, setCustomers] = useState<ICustomer[]>([]);
const getData = (
sourceData: Array<ICustomer>,
searchText: string | undefined
) => {
if (!searchText) {
return sourceData;
}
return sourceData.filter((item) => {
const comparisonString = `${item.firstname.toLowerCase()}${item.familyname.toLowerCase()}`;
//here you can provide a more sophisticared search
return comparisonString.includes(searchText.toLowerCase());
});
};
const columns = [
{
title: "Vorname",
dataIndex: "firstname",
key: "firstname",
sorter: (a: ICustomer, b: ICustomer) => {
if (a.firstname.toLowerCase() > b.firstname.toLowerCase()) {
return -1;
} else if (a.firstname.toLowerCase() < b.firstname.toLowerCase()) {
return 1;
} else {
return 0;
}
},
},
{
title: "Nachname",
dataIndex: "familyname",
key: "familyname",
},
];
return (
<>
<Search
placeholder="Vorname, Nachname"
value={searchText}
onChange={(e) => {
setSearchText(e.target.value);
}}
/>
<Table
columns={columns}
dataSource={getData(customers, searchText)}
/>
</>
);
};
I'm having issue when rendering dynamic columns for Antd table, when I re-render the columns, the table's header just disappear.
getDefaultColumns()
const getDefaultColumns = () => {
return [
{
title: <span className={`table-header`}>STT</span>,
align: "center",
key: "STT",
render: (value, record, index) =>
(currentPage - 1) * pageSize + index + 1,
width: 50,
fixed: "left",
},
{
title: <span className={`table-header pl-4`}>Name</span>,
dataIndex: "full_name",
width: 150,
fixed: "left",
align: "left",
render: (text, record) => (
<span className="pl-4">{record.full_name}</span>
),
},
{
title: <span className={`table-header pl-4`}>Code</span>,
dataIndex: "code",
fixed: "left",
align: "left",
render: (text, record) => <span className="pl-4">{record.code}</span>,
},
{
title: <span className={`table-header`}>DOB</span>,
dataIndex: "birthday",
align: "center",
render: (value) => <span>{moment(value).format(DATE_FORMAT)}</span>,
fixed: "left",
},
{
title: <span className={`table-header`}>SUMMARY</span>,
children: [
{
title: (
<span className={`table-header`}>
TB{" "}
{semester.key !== "whole_year"
? `HK ${semester.shortValue}`
: semester.value}
</span>
),
dataIndex: ["study_summary_info", "average_semester"],
key: "study_summary_info_average_semester",
align: "center",
},
{
title: <span className={`table-header`}>Rank</span>,
key: "study_summary_info_ranked_academic",
align: "center",
render: (value, record) => {
return (
<SelectOption
...
/>
);
},
},
{
title: <span className={`table-header`}>Conduct</span>,
key: "study_summary_info_conduct",
align: "center",
render: (value, record) => {
return (
<SelectOption
...
/>
);
},
},
],
},
{
title: <span className={`table-header`}>Day off</span>,
dataIndex: ["study_summary_info", "day_off"],
key: "study_summary_info_day_off",
align: "center",
},
{
title: <span className={`table-header`}>Title</span>,
key: "study_summary_info_title",
align: "center",
render: (value, record) => {
return (
<SelectOption
...
/>
);
},
},
{
title: <span className={`table-header`}>Result</span>,
key: "study_summary_info_result",
align: "center",
render: (value, record) => {
return (
<SelectOption
...
/>
);
},
},
];
};
setupColumns()
const setupColumns = () => {
filterClassHasSubject({ class_id: classId, page: 1, size: 999 })
.then((res) => {
if (res.data.code === "success") {
const data = res.data.data;
let children = data.map((val) => {
return {
title: (
<span className={`table-header`}>{val.subject_info?.name}</span>
),
key: (value, record, index) => `subject_${index}`,
width: 150,
align: "center",
ellipsis: true,
render: (value, record) => {
const point = record.average_transcript_info.find(
(x) =>
x.subject_id === val.subject_id &&
x.semester === semester.key
);
return (
<span>{point?.value_number}</span>
);
},
};
});
let scoreGroup = {
title: <span className={`table-header`}>DTB</span>,
children,
};
let temp = getDefaultColumns();
temp.splice(4, 0, scoreGroup);
setColumns([...temp]);
}
});
};
Table
<Table
dataSource={summaryData}
columns={columns}
bordered
rowClassName={(record, index) =>
index % 2 === 1
? "odd-row attendance-row"
: "bg-white attendance-row"
}
pagination={false}
scroll={{ x: "100vw", y: 580 }}
/>
This is not happen when I remove the scroll Y on the Table.
The columns is render dynamically when semester or classId is changed.
Before change semester
After change semester
In my case, it was because of the property key in the column. The solution was to use string instead of using the function to return string.
I have created a Material UI DataGrid table and trying to make its fields editable. I am facing an issue while editing the fields using my custom logic. My custom editing logic works when I press enter however when I edit the value and then click outside of the column (somewhere else on the page) the internal value gets updated according to the logic however the displayed cell value doesn't match the updated value, it shows the user-edited value.
import React, { useEffect } from "react";
import { makeStyles, LinearProgress } from "#material-ui/core";
import {
DataGrid,
GridColDef,
GridOverlay,
GridCellEditCommitParams,
GridValueFormatterParams,
} from "#material-ui/data-grid";
const useStyles = makeStyles({
root: {
"& .super-app-theme--header": {
backgroundColor: "#f2f2f2",
},
},
muiGridRoot: {
maxHeight: "77px !important",
"& .MuiDataGrid-columnHeaderTitle": {
fontWeight: "600 !important" as any,
},
},
});
interface props {
coilId: string;
}
export default function TargetMechnicalPropsTable({
coilId,
}: props) {
const classes = useStyles();
const [rows, setRows] = React.useState<any>([
{
id: 1,
UpperLimitValue: 124.232,
lowerLimitValue: 24.232,
targetValue: 67.33,
element: "Yield Strength",
},
]);
const columns: GridColDef[] = [
{
field: "id",
hide: true,
headerClassName: "super-app-theme--header",
sortable: false,
flex: 1,
align: "center",
headerAlign: "center",
},
{
field: "element",
headerName: "Element",
headerClassName: "super-app-theme--header",
editable: false,
sortable: false,
flex: 1,
align: "center",
headerAlign: "center",
},
{
field: "targetValue",
headerName: "Target value",
headerClassName: "super-app-theme--header",
valueFormatter: (params: GridValueFormatterParams) => {
const valueFormatted = Number(params.value as number).toFixed(4);
return `${valueFormatted}`;
},
editable: true,
//type: "number",
sortable: false,
flex: 1,
align: "center",
headerAlign: "center",
},
{
field: "lowerLimitValue",
headerName: "Lower Limit",
headerClassName: "super-app-theme--header",
valueFormatter: (params: GridValueFormatterParams) => {
const valueFormatted = Number(params.value as number).toFixed(4);
return `${valueFormatted}`;
},
editable: true,
sortable: false,
flex: 1,
align: "center",
headerAlign: "center",
},
{
field: "UpperLimitValue",
headerName: "Upper Limit",
headerClassName: "super-app-theme--header",
sortable: false,
valueFormatter: (params: GridValueFormatterParams) => {
const valueFormatted = Number(params.value as number).toFixed(4);
return `${valueFormatted}`;
},
editable: true,
flex: 1,
align: "center",
headerAlign: "center",
},
];
const handleCellEditCommit = React.useCallback(
({ id, field, value }: GridCellEditCommitParams) => {
const updatedRows = rows.map((row: any) => {
if (row.id === id) {
switch (field) {
case "lowerLimitValue":
if (
Number(value) < Number(row.targetValue) &&
Number(value) < Number(row.UpperLimitValue)
) {
return { ...row, lowerLimitValue: Number(value) };
} else {
return {
...row,
lowerLimitValue: Number(row.lowerLimitValue),
};
}
case "UpperLimitValue":
if (
Number(value) > Number(row.targetValue) &&
Number(value) > Number(row.lowerLimitValue)
) {
return { ...row, UpperLimitValue: Number(value) };
} else {
return {
...row,
UpperLimitValue: Number(row.UpperLimitValue),
};
}
case "targetValue":
if (
Number(value) > Number(row.lowerLimitValue) &&
Number(value) < Number(row.UpperLimitValue)
) {
return { ...row, targetValue: Number(value) };
} else {
return {
...row,
targetValue: Number(row.targetValue),
};
}
}
}
return row;
});
setRows(updatedRows);
},
[rows]
);
return (
<div style={{ width: "100%" }} className={classes.root}>
<DataGrid
classes={{
root: classes.muiGridRoot,
}}
rows={rows}
columns={columns}
hideFooterPagination
hideFooter
disableColumnMenu
disableColumnFilter
disableColumnSelector
autoHeight
disableExtendRowFullWidth
density="compact"
onCellEditCommit={handleCellEditCommit}
/>
</div>
);
}
Please let me know what needs to be done for my custom logic to work when the user clicks outside of the column while editing it so that the user displayed value matches with the internal logic value.
Thank you!
I am using react-table plugin, and my cells keep re-rendering while I am changing the applied searching filter even though their values aren't changed.
As seen in the video, name and debt TDs keep updating, even though their values are static.
https://i.imgur.com/2KkNs9f.mp4
I imagine, that may impact performance on larger tables.
Is there any fix? Or am I doing anything wrong?
Thanks.
Edit:
Code has been requested. Not much to show, basically everything done as in documentation.
Rendering part:
render(){
const columns = [
{
Header: "Name",
accessor: "name",
className: css.cell,
headerClassName: css.cell,
filterMethod: (filter, row) => {
return row[filter.id]
.toLowerCase()
.includes(filter.value.toLowerCase());
},
Cell: props => {
return <span>{props.value}</span>;
}
},
{
Header: "Tc",
accessor: d => {
const date = d.lastChange;
if (date.length) {
const s = date.split(" ");
const s2 = s[0].split("/");
const mdy = [s2[1], s2[0], s2[2]].join("/");
const his = s[1];
return Date.parse(mdy + " " + his);
}
return "";
},
id: "lastChange",
Cell: props => {
return <ArrowTime lastChange={props.value}></ArrowTime>;
},
headerClassName: css.cell,
className: css.cell
},
{
Header: "Debt",
accessor: d => Number(d.lastDebt),
id: "lastDebt",
headerClassName: css.cell,
className: css.cell,
Cell: props => {
return <span className="number">{props.value}</span>;
},
getProps: (state, rowInfo, column) => {
return {
style: {
background: rowInfo ? this.getColor(rowInfo.row.lastDebt) : null
}
};
}
}
];
return (
<ReactTable
data={this.props.table}
columns={columns}
minRows={0}
showPagination={false}
NoDataComponent={CustomNoDataComponent}
className={css.table}
resizable={false}
filtered={[{ id: "name", value: this.props.filter }]}
getTrProps={(state, rowInfo) => {
return {
className: rowInfo ? css.subRow : ""
};
}}
getTrGroupProps={(state, rowInfo) => {
return {
className: rowInfo ? css.row : ""
};
}}
getTbodyProps={props => {
return {
className: props ? css.tbody : ""
};
}}
getTheadProps={props => {
return {
className: props ? css.thead : ""
};
}}
defaultSorted={[
{
id: "lastDebt",
desc: true
}
]}
/>
);
}