How to expand Antd table row by click a button - antd

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")
);

Related

Conflict on the React ant design table input total balance

Im tried to do some calculate part for my react ant design 4 table, i don't have idea for how to get when i entered value after get automatically calculate total and then submit. any onw know how to do that correctly.
Thanks
stack blitz here
This is my code part
const columns = [
{
title: 'Name',
dataIndex: 'name',
key: 'name',
render: text => <a>{text}</a>,
},
{
title: 'Book',
dataIndex: 'book',
key: 'book',
},
{
title: 'Pen',
dataIndex: 'pen',
key: 'pen',
},
{
title: 'Tools',
key: 'tools',
dataIndex: 'tools',
},
{
title: 'Total',
key: 'total',
dataIndex: 'total',
},
];
const data = [
{
key: '1',
name: 'John Brown',
book: <Form.Item name="book1" rules={[{required: true, message: " is required"}]}><Input style={{width: 150}}/></Form.Item>,
pen: <Form.Item name="oen1" rules={[{required: true, message: "is required"}]}><Input style={{width: 150}}/></Form.Item>,
tools: <Form.Item name="tools1" rules={[{required: true, message: " is required"}]}><Input style={{width: 150}}/></Form.Item>,
total:'00000'
},
];
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>
</div>
</Form>
</div>, document.getElementById('container'));
I assumed the rows can be more than one. You can achieve this by:
You need a state. In react, in order to change something on the UI (e.g. total column) you need a state. Put your data array in state.
const [data, setData] = useState([ ... ])
You need to know which row the input was when you type in. You may add some distinction on input that is equal to row key. Here I suggest to put some number on the name of input:
<Form.Item name="book-1">...</Form.Item>
<Form.Item name="pen-1">...</Form.Item>
<Form.Item name="tools-1">...</Form.Item>
Use onValuesChange prop of the <Form> it triggers every time you type on the inputs and return the form values. With this, you can extract the number on input name and use that as a reference to know which row is about to change and perform setState.
I also suggest to use InputNumber instead of Input if you only need a number input.
Here is the working link. You can start/play around there if I did not hit what you want.
You may also look on antd table editable rows. This might be easiest to use than this

how to hide columns of antd data table for small devices(mobile view)?

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

Different row data in Nested Table Row

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

How to highlight tree node on click of button in element-ui

I am having el-tree> element and 1 button showNode.
so on click of this button i want to highlight a node with given index.
How to call highlight-current on click of button?
From documentation:
highlight-current: whether current node is highlighted
highlight-current is just a read-only attribute, in order to highlight a specific node, you have to call the method setCurrentKey
setCurrentKey: set highlighted node by key, only works when node-key is assigned, the param (key) is the node's key to be highlighted
So, you need first to add a key to every node, using the property key:
node-key: unique identity key name for nodes, its value should be unique across the whole tree
Like following example:
<el-tree
:data="myData"
node-key="id">
</el-tree>
And then, call the method setCurrentKey on the click event attached to your button:
<el-button #click="setCurrentKey(myData[index].id)">Highlight the n-index node</el-button>
I hope it helps you, bye.
Updated: The code above works only on 2.x version, here an example to highlite a node on version 1.4.13 (but I can't expand a node, so I had to expand all the tree):
var Main = {
data() {
return {
data: [{
label: 'Level one 1',
id: 1,
children: [{
label: 'Level two 1-1',
id: 11
}]
}, {
label: 'Level one 2',
id: 2,
children: [{
label: 'Level two 2-1',
id: 21,
children: [{
label: 'Level three 2-1-1',
id: 211
}]
}, {
label: 'Level two 2-2',
id: 22,
children: [{
label: 'Level three 2-2-1',
id: 221
}]
}]
}],
defaultProps: {
children: 'children',
label: 'label'
}
};
},
methods: {
handleNodeClick(data) {
console.log(data);
},
renderContent(h, { node, data, store }) {
let btn = h('span', {
props: {type: 'success'},
domProps: {
innerHTML: data.label,
id: "node-id-" + data.id
}
})
return btn
},
handleBtnClick(){
//Highlite the 211
document.getElementById("node-id-211").style.backgroundColor="yellow";
}
}
};
var Ctor = Vue.extend(Main)
new Ctor().$mount('#app')
#import url("//unpkg.com/element-ui#1.4.13/lib/theme-default/index.css");
<script src="//unpkg.com/vue/dist/vue.js"></script>
<script src="//unpkg.com/element-ui#1.4.13/lib/index.js"></script>
<div id="app">
<el-tree :data="data" :props="defaultProps" #node-click="handleNodeClick" :render-content="renderContent" :default-expand-all="true"></el-tree>
<el-button #click="handleBtnClick">Highlight the 211 node</el-button>
</div>

jQuery Select2 - Highlighting the child (when the search term matches) instead of its parent in hierarchical list

Select2 3.5.2.
I have some hierarchical data in a select2 list where the parents AND children are all valid selections. If possible, when the search term matches a child, I'd like the child to be highlighted by default instead of the parent.
For example, given the following code...
$("#hdn").select2(
{
width: '300px',
data:
[
{
id: 1,
text: 'Italy',
children:
[
{ id: 2, text: 'Italy - Sardinia' },
{ id: 3, text: 'Italy - Sicily' },
]
},
{
id: 4,
text: 'United Kingdom',
children:
[
{ id: 5, text: 'United Kingdom - Guernsey' },
{ id: 6, text: 'United Kingdom - Jersey' }
]
}
]
});
... if you start typing 'Jer', it currently highlights 'United Kingdom' by default:
Ideally, if you start typing 'Jer', it should highlight 'United Kingdom - Jersey' by default instead.
Because this is a group I still want the parent to show as an option, I just want the child to be highlighted by default instead.
See this fiddle: http://jsfiddle.net/moo_ski_doo/atnph13b/2/
Select2 will highlight the first option which is selectable by default. If you don't want the highlight to sit on "United Kingdom" first, you are going to have to remove the id.
Select2 3.5.2 does not provide an easy way to change how what option is highlighted by default.

Resources