Adding multiple data to a column in react-table - reactjs

I have a table using react-table but for one of the columns I want to show two pieces of data - name and description.
getInitialState(){
return {
data: [{
id: 1,
keyword: 'Example Keyword',
product: [
name: 'Red Shoe',
description: 'This is a red shoe.'
]
},{
id: 2,
keyword: 'Second Example Keyword',
product: [
name: 'blue shirt',
description: 'This is a blue shirt.'
]
}]
}
},
render(){
const { data } = this.state;
return (
<div className="app-body">
<ReactTable
data={data}
columns={[{
columns: [{
Header: 'Id',
accessor: id,
show: false
}, {
Header: 'Keyword',
accessor: 'keyword'
}, {
Header: 'Product',
accessor: 'product' // <<< here
}]
}]}
defaultPageSize={10}
className="-highlight"
/>
</div>
)
}
Where the accessor is Product I want to show both the name and description (I'll style them to stack with different font sizes) in the Product column.
I've tried using the Cell: row => attribute for that column and thought I could also try calling a function that lays it out, but I've gotten errors both times.
Any ideas how to do this?

Indeed you should use Cell for this like this:
getInitialState(){
return {
data: [
{
id: 1,
keyword: 'Example Keyword',
product: [
name: 'Red Shoe',
description: 'This is a red shoe.'
]
},{
id: 2,
keyword: 'Second Example Keyword',
product: [
name: 'blue shirt',
description: 'This is a blue shirt.'
]
}]
}
},
render(){
const { data } = this.state;
return (
<div className="app-body">
<ReactTable
data={data}
columns={[{
columns: [{
Header: 'Id',
accessor: id,
show: false
}, {
Header: 'Keyword',
accessor: 'keyword'
}, {
Header: 'Product',
accessor: 'product',
Cell: ({row}) => { //spread the props
return (
<div>
<span className="class-for-name">{row.product.name}</span>
<span className="class-for-description">{row.product.description}</span>
</div>
)
}
}]
}]}
defaultPageSize={10}
className="-highlight"
/>
</div>
)
}
Another thing I spotted was that product property should be an object not an array, so change this:
product: [
name: 'blue shirt',
description: 'This is a blue shirt.'
]
to this:
product: {
name: 'blue shirt',
description: 'This is a blue shirt.'
}

The accepted answer didn't work for me. Here's how I did it:
const [data, setData] = React.useState([
{
name: 'My item',
desc: 'This is a nice item',
},
]);
const columns = React.useMemo(() => [
{
Header: 'Name',
accessor: 'name',
Cell: (props) => (
<>
<p className="item title">{props.row.original.name}</p>
<p className="item desc">{props.row.original.desc}</p>
</>
),
},
]);

Related

Infinite loop in Material UI onSortModelChange(React js)

Documentation: https://v4.mui.com/components/data-grid/sorting/#data-grid-sorting
const [sortModel, setSortModel] = React.useState([
{
field: 'name',
sort: 'asc',
},]);
const columns = [
{ field: 'name' },
{ field: 'school'}]
const rows = [
{ id: 1, name: 'React', school: 'abc' },
{ id: 2, name: 'Material-UI', school: 'pqr' },]
<DataGrid
columns={columns}
rows={rows}
sortingOrder={['desc', 'asc']}
sortModel={sortModel}
onSortModelChange={(model) => setSortModel(model)}
/>
Clicking on the sort button causes infiite loop

How to format a cell in react material-ui DataGrid

I have a react material-ui DataGrid.
One of the cells shows text data representing status, which I want to show in a graphical way - specifically bootstrap badge.
The DataGrid code is:
const ProcessesColumns: ColDef[] = [
{ field: 'id', headerName: 'ID' },
{ field: 'name', headerName: 'Name', width: 300 },
{ field: 'status', headerName: 'Status', width: 130 },
];
const processes = [
{
id: 1,
name: 'aaa',
status: 'Sucess',
},
{
id: 2,
name: 'bbb',
status: 'Fail',
},
{
id: 3,
name: 'ccc',
status: 'Sucess',
},
{
id: 4,
name: 'ddd',
status: 'Success',
},
{
id: 5,
name: 'eee',
status: 'Sucess',
},
{
id: 6,
name: 'fff',
status: 'Fail',
},
]
<DataGrid rows={processes} columns={ProcessesColumns} pageSize={10} />
I think you should check this
You can add a renderCell attribute on your status column definition
I think you can do it with renderCell. Here's an example of something similar, and I hope it helps.
I have a column which cells I want to format to have an icon and a value, and I created that in a format function:
const priorityFormater = (cell) => {
return (
<span>
<GrStatusGoodSmall className={taskPriorityColor(cell)} />
<span className="priority-span">{cell}</span>
</span>
);
};
Column definition:
{
field: "priority",
headerName: "Priority",
flex: 0,
minWidth: 140,
renderCell: (params) => {
return priorityFormater(params.value);
},
},
Result:

Adding button inside Ant-design table column

I want to create a button inside table column. I have tried using Cell but its not working.
Cell: ({ cell }) => (
<button value={cell.row.values.name} onClick={props.handleClickGroup}>
{cell.row.values.name}
</button>
)
You can render a button inside column using the render property:
const columns = [
{
title: 'Button Test',
key: 'key',
dataIndex: 'key',
render: (text, record) => (
<button onClick={()=> console.log(record)}>
{"Button Text"}
</button>
),
},
];
const data = [
{
key: '1',
name: 'John Doe',
age: 35,
address: 'New York No. 1 Lake Park'
},
];
<Table
columns={columns}
dataSource={data}
/>
If it is ant-design for Vue you can try this:
Template
<template>
<a-table :columns="columns" :data-source="data">
<a-button slot="action">{ buttonText }</a-button>
</a-table>
</template>
Script
<script>
const columns = [
{ title: 'Name', dataIndex: 'name', key: 'name' },
{ title: 'Age', dataIndex: 'age', key: 'age' },
{ title: 'Address', dataIndex: 'address', key: 'address' },
{ title: 'Action', dataIndex: '', key: 'x', scopedSlots: { customRender: 'action' } },
]
const data = [
{
key: 1,
name: 'John Brown',
age: 32,
address: 'New York No. 1 Lake Park',
description: 'My name is John Brown, I am 32 years old, living in New York No. 1 Lake Park.',
},
{
key: 2,
name: 'Jim Green',
age: 42,
address: 'London No. 1 Lake Park',
description: 'My name is Jim Green, I am 42 years old, living in London No. 1 Lake Park.',
},
]
export default{
data(){
return{
data,
columns,
buttonText: "view"
}
}
}
</script>
You can find more information on their site https://antdv.com/components/table/ under Expandable Row

Ant design sort table code not working on the react typescript

I used following ant design sort table code in react type script, its not working correctly anyone know how to do that correctly
My code here
import { Table } from 'antd';
import * as React from 'react';
import { Table } from 'antd';
const columns = [
{
title: 'Name',
dataIndex: 'name',
filters: [
{
text: 'Joe',
value: 'Joe',
},
{
text: 'Jim',
value: 'Jim',
},
{
text: 'Submenu',
value: 'Submenu',
children: [
{
text: 'Green',
value: 'Green',
},
{
text: 'Black',
value: 'Black',
},
],
},
],
// specify the condition of filtering result
// here is that finding the name started with `value`
onFilter: (value:any, record:any) => record.name.indexOf(value) === 0,
sorter: (a:any, b:any) => a.name.length - b.name.length,
sortDirections: ['descend'],
},
{
title: 'Age',
dataIndex: 'age',
defaultSortOrder: 'descend',
sorter: (a:any, b:any) => a.age - b.age,
},
{
title: 'Address',
dataIndex: 'address',
filters: [
{
text: 'London',
value: 'London',
},
{
text: 'New York',
value: 'New York',
},
],
filterMultiple: false,
onFilter: (value:any, record:any) => record.address.indexOf(value) === 0,
sorter: (a:any, b:any) => a.address.length - b.address.length,
sortDirections: ['descend', 'ascend'],
},
];
const data = [
{
key: '1',
name: 'John Brown',
age: 32,
address: 'New York No. 1 Lake Park',
},
{
key: '2',
name: 'Jim Green',
age: 42,
address: 'London No. 1 Lake Park',
},
{
key: '3',
name: 'Joe Black',
age: 32,
address: 'Sidney No. 1 Lake Park',
},
{
key: '4',
name: 'Jim Red',
age: 32,
address: 'London No. 2 Lake Park',
},
];
function onChange(pagination:any, filters:any, sorter:any, extra:any) {
console.log('params', pagination, filters, sorter, extra);
}
//Table sample data
export class Customertable extends React.Component {
render() {
return (
/* Start Search button*/
<div className="customertable-section">
<div>
<Table columns={columns} dataSource={data} onChange={onChange} />
</div>
</div>
/* End of Search button*/
);
}
}
While declaring the variable in typescript, you need to give it like, columns: any = [] and data: any = []..
And while making table , you should give the props like,
<Table columns={this.columns} dataSource={this.data} />
Working sample antd table with typescript here...
To add on to Maniraj's comment, the documentation provides a section for Typescript specific usage:
https://ant.design/components/table/#Using-in-TypeScript
Setting the type of columns is possible by importing ColumnsType from 'antd/es/table'
Here the solution that may help someone. You should write type for your table config using default ant types and then in compare func, your item is DefaultRecordType, func returns number.
const TABLE_COLUMNS: ColumnsType<DefaultRecordType> = [
{
title: 'ISO #',
dataIndex: 'iso',
key: 'iso',
sorter: (a: DefaultRecordType, b: DefaultRecordType): number =>
a.iso.localeCompare(b.iso),
},]
You can simply sort your ant design table's column by replace your old code with new:
Old Code:
sorter: (a:any, b:any) => a.name.length - b.name.length,
New Code:
sorter: (a:any, b:any) => a.name.localeCompare(b.name),

How to add dynamic link to table data

I'm working on a simple table using ReactJs and ant design, my problem is I don't know how to put value on the links using their data keys.
Thanks,
Codepen
SAMPLE CODE
const { Table } = antd;
const columns = [{
title: 'Name',
dataIndex: 'name',
render: text => {text},
}, {
title: 'Cash Assets',
className: 'column-money',
dataIndex: 'money',
}, {
title: 'Address',
dataIndex: 'address',
}];
const data = [{
key: '1',
name: 'John Brown',
money: '¥300,000.00',
address: 'New York No. 1 Lake Park',
}, {
key: '2',
name: 'Jim Green',
money: '¥1,256,000.00',
address: 'London No. 1 Lake Park',
}, {
key: '3',
name: 'Joe Black',
money: '¥120,000.00',
address: 'Sidney No. 1 Lake Park',
}];
ReactDOM.render(
<Table
columns={columns}
dataSource={data}
bordered
title={() => 'Header'}
footer={() => 'Footer'}
/>
, mountNode);
Change this
render: text => {text}
to this
render: (text, record) => <a href={'user/' + record.name}>{text}</a>
if you're using router
render: (text, record) => <Link to={'user/' + record.name}>{text}</Link>
As you can see, the column rendering logic is provided by the columns array of objects. So if you want to include any logic ( like giving values to URLs ), you have to alter the corresponding object's render key:
const columns = [{
title: 'Name',
dataIndex: 'name',
render: text => <a href={`http://<some-domain>.com/user/${text.split(' ').join()}`}>{text}</a>, // changed function, so that data maps to links. eg: http:??<some-domain>.com/user/JohnBrown
}, {
/* */
}, {
/* */
}];
Alternatively, you could create an object for looking up urls, like so:
const mapping = {
'John Brown': 'http://yourdomain.com/user/134123',
'Jin Green': 'http://yourdomain.com/user/897983',
/* more persons */
}
const columns = [{
title: 'Name',
dataIndex: 'name',
render: text => <a href={mapping[text]}>{text}</a>, // changed function
}, {
/* */
}, {
/* */
}];

Resources