I am using Ant Design for my project. I have a scene where i should use Ant Design Nested Table where in every row opens new nested Table to show data. I am not able to show different data for each row. It is showing same data in all Nested rows
This is what i am using
https://ant.design/components/table/#components-table-demo-nested-table
Code is as such from Official Doc
Expecting to show different data in different nested row items
Inside expandedrow function you can pass a row parameter. Based on the row you can render your own table.
https://codesandbox.io/s/34w7km6o11
In the above sample, you can check how i rendered different data based on that particular row.
I used ternary operator, You can write your own condition
import React from "react";
import ReactDOM from "react-dom";
import "antd/dist/antd.css";
import "./index.css";
import { Table } from "antd";
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",
render: () => Delete
}
];
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."
},
{
key: 3,
name: "Joe Black",
age: 32,
address: "Sidney No. 1 Lake Park",
description:
"My name is Joe Black, I am 32 years old, living in Sidney No. 1 Lake Park."
}
];
const data1 = [
{
key: 1,
name: "I am diff",
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: "yes",
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."
},
{
key: 3,
name: "no",
age: 32,
address: "Sidney No. 1 Lake Park",
description:
"My name is Joe Black, I am 32 years old, living in Sidney No. 1 Lake Park."
}
];
const data2 = [
{
key: 1,
name: "hello",
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: "hi",
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."
},
{
key: 3,
name: "test",
age: 32,
address: "Sidney No. 1 Lake Park",
description:
"My name is Joe Black, I am 32 years old, living in Sidney No. 1 Lake Park."
}
];
const expandedRow = row => {
console.log(row);
let inTable = row.key == 1 ? data1 : row.key == 2 ? data2 : data;
return <Table columns={columns} dataSource={inTable} pagination={false} />;
};
ReactDOM.render(
<Table columns={columns} expandedRowRender={expandedRow} dataSource={data} />,
document.getElementById("container")
);
I have a different approach to this problem, I have been looking around in other posts and have not found this solution, I hope it helps:
import React from "react";
import "antd/dist/antd.css";
import { Table } from "antd";
import { fakeFirstLevelData } from
'../fakeDataBase/fakeFirstLevelData'
const firstLevelColumns = [
{
title: 'ID',
dataIndex: 'id_tx',
key: 'ID_TX'
},
{
title: 'Amount',
dataIndex: 'amount',
key: 'amount'
},
{
title: 'Currency',
dataIndex: 'currency',
key: 'currency'
},
]
const secondLevelColumns = [
{
title: 'First name from',
dataIndex: 'firstname_from',
key: ''
},
{
title: 'first name to',
dataIndex: 'firstname_to',
key: ''
},
{
title: 'Date ',
dataIndex: 'date',
key: ''
},
]
const firstExpandedRow = (record, index, indent, expanded) => {
let data = []
data.push(record.secondLevel)
return (
<Table
rowKey={record => record.cardholderid}
columns={secondLevelColumns}
dataSource={data}
// expandable={{ expandedRowRender: secondExpandedRow }}
pagination={false}
/>
)
}
return (
<div className='container mt-40 mb-40 overflow-x-auto
tableContainer'>
<Table
dataSource={fakeFirstLevelData}
columns={firstLevelColumns}
rowKey={record => record.id_tx}
loading={fakeFirstLevelData ? false : true}
pagination={false}
expandable={{
expandedRowRender: firstExpandedRow,
defaultExpandAllRows: false
}}
/>
</div>
)
This is my fake data , its similar to call a API:
export const fakeFirstLevelData = [
{
id: '1199343457',
amount: '127,45',
currency: 'EUR',
secondLevel: {
firstnameFrom: 'Antonio',
firstnameTo: 'Juan',
date: '2024/12/12'
}
},
{
id: '11993453458',
amount: '1',
currency: 'EUR',
secondLevel: {
firstnameFrom: 'Carlos',
firstnameTo: 'EstefanÃa',
date: '2024/12/12'
}
}
]
This way I have a json with different levels of information and in each row I can show N fields and by expanding the rows I can show more information of the same row.
make children data with state
then pass it to the expan function
write the parameter with free text
then inside nested table write data[expan.key].children2 inside datasource of nested table.
data[expan.key].children2 is just free text you can change with other. thank you
Related
I have a List of Objects in the file list.dart:
final itemList = [
ItemData(uuid: 'one', score: '30', title: 'Title One', description: 'mock description'),
ItemData(uuid: 'two', score: '10', title: 'Title Two', description: 'mock description'),
ItemData(uuid: 'three', score: '20', title: 'Title Three', description: 'mock description'),
];
I am calling back UUID: 'one' to another widget in the file edit.dart
return GestureDetector(
onTap: (){
currentItem = item.uuid; //currentItem declared in file edit.dart
DisplayItem(); //callback function to edit.dart
},
child: Card(
My plan is to use the callback function to get the elements with the corresponding uuid. My problem is I can't figure out how to find the index of the object with the element equal to a given uuid. I've tried nesting indexOf() but get exponentially confused.
So if I understand correctly, you have a list of items and you want to find the index of the first item that fulfils a condition (in this case the condition is that the items UUID value is equal to some value)
In order to do something like that, you can use the indexWhere method:
var targetUuid = 'one';
int itemIndex = itemList.indexWhere((item) => item.uuid == targetUuid);
print(itemList[itemIndex]);
you can find the index of object as:
void main() {
final List<Map<String, dynamic>> _people = [
{"id": "c1", "name": "John Doe", "age": 40},
{"id": "c2", "name": "Kindacode.com", "age": 3},
{"id": "c3", "name": "Pipi", "age": 1},
{"id": "c4", "name": "Jane Doe", "age": 99},
];
// Find index of the person whose id = c3
final index1 = _people.indexWhere((element) => element["id"] == "c3");
if (index1 != -1) {
print("Index $index1: ${_people[index1]}");
}
// Find the last index where age > 80
final index2 = _people.lastIndexWhere((element) => element["age"] > 80);
if (index2 != -1) {
print("Index $index2: ${_people[index2]}");
}
}
Output:
Index 2: {id: c3, name: Pipi, age: 1}
Index 3: {id: c4, name: Jane Doe, age: 99}
Im adding my react project for ant design4 table and ant design input fields. any one know to how can validate that input required
Thanks
stackablitz here
code here
const columns = [
{
title: 'Name',
dataIndex: 'name',
key: 'name',
render: text => <a>{text}</a>,
},
{
title: 'Age',
dataIndex: 'age',
key: 'age',
},
{
title: 'Address',
dataIndex: 'address',
key: 'address',
},
{
title: 'Tags',
key: 'tags',
dataIndex: 'tags',
render: tags => (
<>
{tags.map(tag => {
let color = tag.length > 5 ? 'geekblue' : 'green';
if (tag === 'loser') {
color = 'volcano';
}
return (
<Tag color={color} key={tag}>
{tag.toUpperCase()}
</Tag>
);
})}
</>
),
},
{
title: 'Action',
key: 'action',
render: (text, record) => (
<Space size="middle">
<a>Invite {record.name}</a>
<a>Delete</a>
</Space>
),
},
];
const data = [
{
key: '1',
name: 'John Brown',
age: <input/>,
address: 'New York No. 1 Lake Park',
tags: ['nice', 'developer'],
},
{
key: '2',
name: 'Jim Green',
age: <input/>,
address: 'London No. 1 Lake Park',
tags: ['loser'],
},
{
key: '3',
name: 'Joe Black',
age: <input/>,
address: 'Sidney No. 1 Lake Park',
tags: ['cool', 'teacher'],
},
];
const onFinish = values => {
console.log(values);
};
ReactDOM.render(
<div>
<Form name="control-hooks" onFinish={onFinish}>
<Table columns={columns} dataSource={data} /> <div><Form.Item>
<Button type="primary" htmlType="submit">
Submit
</Button> </Form.Item>
Just enclose the <input/> in <Form.Item> and use the rules prop of it. You can see all the possible rules here. I suggest use the <Input/> of antd and set a width on it.
const data = [
{
key: "1",
name: "John Brown",
age: (
<Form.Item
name="age1"
rules={[{ required: true, message: "Age is required" }]}
>
<Input style={{ width: 150 }} />
</Form.Item>
),
address: "New York No. 1 Lake Park",
tags: ["nice", "developer"],
},
...
];
see this working link
If the table has five columns i want to display only 2 columns for mobile view
https://ant.design/components/table
you can keep columns in component state and dynamically filter the columns on window resize. Something like this
useEffect(() => {
window.addEventListener("resize", <callback function to update columns>);
// cleanup
return() => window.removeEventListener("resize");
});
Inside render method you need to declare columns with let and change them if window.innerWidth < 480 (I made it less then 500 px to be safe). By changing, I mean filtering from an array of columns only those columns that you want. The best way to filter is by key, because it's unique. This is how the code looks in react:
import React, { PureComponent } from "react";
import { Table } from "antd";
export default class MainPage extends PureComponent {
renderMobileTable = columns => {
return columns.filter(
column => column.key === "name" || column.key === "city"
);
};
render() {
const dataSource = [
{
key: "1",
name: "Mike",
lastName: "Willins",
age: 32,
address: "10 Downing Street",
city: "Chicago"
},
{
key: "2",
name: "John",
lastName: "Billards",
age: 42,
address: "5th Blvd",
city: "New York"
}
];
let columns = [
{
title: "Name",
dataIndex: "name",
key: "name"
},
{
title: "Last Name",
dataIndex: "lastName",
key: "lastName"
},
{
title: "Age",
dataIndex: "age",
key: "age"
},
{
title: "Address",
dataIndex: "address",
key: "address"
},
{
title: "City",
dataIndex: "city",
key: "city"
}
];
const isMobile = window.innerWidth < 500;
if (isMobile) {
columns = this.renderMobileTable(columns);
}
return <Table dataSource={dataSource} columns={columns} />;
}
}
For the source code you may refer to my repository on GitHub.
NOTE: if you are testing mobile view in Chrome Dev Tools, make sure you reload the page after resizing, as we put the logic into render method and the application has to be re-rendered or reloaded.
In antd v4 you can use column prop 'responsive'
const columns = [{
title: 'identification number',
dataIndex: 'ID',
responsive: ['sm'],
}]
https://ant.design/components/table/#Column
Version
3.0.3
Environment
pc, chrome
Reproduction link
https://codesandbox.io/s/my02ok19wy
Steps to reproduce
now, Table can expand row by two ways:
use icon in the first column
click the whole row with expandRowByClick as true.
But those are not what I want. I want to use the button in some other column, maybe the button Show More. Then, when I click Show More, the row will expand. How to realize this?
Like the demo shows, I want to expand the row by click Show More instead of click the button in the first cell. Thanks
What is expected?
expand one row by click one button not in the first cell
What is actually happening?
Must click the button in the first cell of the row. The button can't move to other cell.
It's possible but I prefer not to do the code for you, but I will explain how.
There is a props call expandedRowKeys where you specify keys of rows that you want to expand.
so
adding expandedRowKeys={[1,3]} to <Table /> will expand the first and the third row.
Now, you just need to implement the handleClickMore function to manipulate an array of row keys. and how something like
expandedRowKeys={this.state.expandedKeys}
You can use expandIcon and expandedRowRender for your purpose
This is the modified code:
import React from "react";
import ReactDOM from "react-dom";
import { version, Table, Button } from "antd";
import "antd/dist/antd.css";
const columns = [
{ title: "Name", dataIndex: "name", key: "name" },
{ title: "Age", dataIndex: "age", key: "age" },
{ title: "Address", dataIndex: "address", key: "address" },
{ title: "Action", dataIndex: "", key: "expand" }
];
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."
},
{
key: 3,
name: "Joe Black",
age: 32,
address: "Sidney No. 1 Lake Park",
description:
"My name is Joe Black, I am 32 years old, living in Sidney No. 1 Lake Park."
}
];
ReactDOM.render(
<div style={{ margin: 24 }}>
<p style={{ marginBottom: 24 }}>
Current antd version: {version} <br />
You can change antd version on the left panel (Dependencies section).
</p>
<Table
// expandIconColumnIndex={3}
columns={columns}
expandedRowRender={(record) => (
<p style={{ margin: 0 }}>{record.description}</p>
)}
dataSource={data}
expandIcon={({ expanded, onExpand, record }) =>
expanded ? (
<Button
onClick={(e) => onExpand(record, e)}
>
Collapse
</Button>
) : (
<Button onClick={(e) => onExpand(record, e)}>Expand</Button>
)
}
/>
</div>,
document.getElementById("root")
);
I have just started using jsPDF and the AutoTable plugin, and it is almost perfect for what we are using it for. One question...
Is it possible to assign a dataKey in the columns definition to a nested property within the JSON that is being mapped to the table?
We have a JSON structure that looks like this:
"Primary_Key": "12345",
"Site_Name": {
"Address_Name": "Address 1"
},
"Default_Screen_Name": "Bob",
"Full_Name": "Bob Smith"
If we use the following columns:
var columns = [
{ title: "ID", dataKey: "Primary_Key" },
{ title: "Screen Name", dataKey: "Default_Screen_Name" },
{ title: "Full Name", dataKey: "Full_Name" }];
Everything works perfectly. However, we would also like to do something like the following:
var columns = [
{ title: "ID", dataKey: "Primary_Key" },
{ title: "Iterations", dataKey: "Iterations" },
{ title: "Screen Name", dataKey: "Default_Screen_Name" },
{ title: "Site Name", dataKey: "Site_Name.Address_Name" }];
Where we are using Site_Name.Address_Name to index into the nested JSON object to retrieve the value.
Is something like this possible?
Not at the moment. You can follow that feature request here. Your options are currently to either flatten the data before passing it to autotable or use the hooks to extract the specific text you want. That can be done like this:
var columns = [
{title: "ID", dataKey: "id"},
{title: "Name", dataKey: "name"},
{title: "Country", dataKey: "address"}
];
var rows = [
{id: 1, name: "Shaw", address: {country: "Tanzania"}},
{id: 2, name: "Nelson", address: {country: "Kazakhstan"}},
{id: 3, name: "Garcia", address: {country: "Madagascar"}}
];
var doc = jsPDF();
doc.autoTable(columns, rows, {
didParseCell: function(data) {
if (data.column.dataKey === 'address') {
data.cell.text = data.cell.raw.country;
}
}
});
doc.save('table.pdf');
<script src="https://unpkg.com/jspdf#1.3.3/dist/jspdf.min.js"></script>
<script src="https://unpkg.com/jspdf-autotable#2.3.1/dist/jspdf.plugin.autotable.js"></script>
Update for additional question in comments:
var columns = [
{title: "Country", dataKey: "address", displayProperty: "country"},
...
];
var rows = [...];
...
didParseCell: function(data) {
if (data.column.dataKey === 'address') {
var prop = data.column.raw.displayProperty;
data.cell.text = data.cell.raw[prop];
}
}