Reputation: 344
I have a table which have a setting icon as the last column and whenever a user clicks on it, it should pop open a setting menu. To toggle between active class I used state
and passed it to the array.map
function, but what is happening is whenever a user clicks on one setting icon all the menus open simultaneously and the reason is they all have same click event and same state variable. How can I change it to where only the clicked setting icon should have its menu opened? My code is given below.
import React, { Component, PropTypes } from 'react';
import '../../../assets/custom_css/tables/unstackable_very_basic_striped_users_table.css';
import { v4 } from 'node-uuid';
import Language from '../../../assets/language';
class UnstackableVeryBasicStripedUsersTable extends Component {
static propTypes = {
rows: PropTypes.array.isRequired
};
constructor(props) {
super(props);
this.getTableRows = this.getTableRows.bind(this);
this.open_setting_menu = this.open_setting_menu.bind(this);
this.state = {
is_action_menu_active: false
};
}
getTableRows() {
const { rows } = this.props;
return rows.map(row => {
let drop_down_class = (this.state.is_action_menu_active) ? "active" : "";
let menu_class = (this.state.is_action_menu_active) ? "transition visible" : "";
return <tr key={v4()}>
{row.map(info => {
return <td key={v4()}>
{info}
</td>
})}
<td>
<div className={"ui right pointing dropdown icon " + drop_down_class} onClick={this.open_setting_menu}>
<i className="setting icon"/>
<div className={"menu " + menu_class}>
<div className="item">Edit</div>
<div className="item">Delete</div>
</div>
</div>
</td>
</tr>
});
}
open_setting_menu() {
this.setState({
is_action_menu_active: !this.state.is_action_menu_active
});
}
render() {
return <table className="ui unstackable celled very basic striped table unstackable_very_basic_striped_table">
<thead>
<tr>
<th>{Language.name}</th>
<th>{Language.role}</th>
<th>{Language.department}</th>
<th>{Language.action}</th>
</tr>
</thead>
<tbody>
{this.getTableRows()}
</tbody>
</table>
}
}
export default UnstackableVeryBasicStripedUsersTable;
Upvotes: 0
Views: 2057
Reputation: 2223
If you want to use a single component, you can save the index of the selected row in the state:
import React, { Component, PropTypes } from 'react';
import '../../../assets/custom_css/tables/unstackable_very_basic_striped_users_table.css';
import { v4 } from 'node-uuid';
import Language from '../../../assets/language';
class UnstackableVeryBasicStripedUsersTable extends Component {
static propTypes = {
rows: PropTypes.array.isRequired
};
constructor(props) {
super(props);
this.getTableRows = this.getTableRows.bind(this);
this.open_setting_menu = this.open_setting_menu.bind(this);
this.state = {
selected_row_index: 0,
is_action_menu_active: false
};
}
getTableRows() {
const { rows } = this.props;
return rows.map((row, index) => {
let drop_down_class = (this.state.is_action_menu_active && this.state.selected_row_index === index) ? "active" : "";
let menu_class = (this.state.is_action_menu_active && this.state.selected_row_index === index) ? "transition visible" : "";
return <tr key={v4()}>
{row.map(info => {
return <td key={v4()}>
{info}
</td>
})}
<td>
<div className={"ui right pointing dropdown icon " + drop_down_class} onClick={() => this.open_setting_menu(index)}>
<i className="setting icon"/>
<div className={"menu " + menu_class}>
<div className="item">Edit</div>
<div className="item">Delete</div>
</div>
</div>
</td>
</tr>
});
}
open_setting_menu(index) {
this.setState({
is_action_menu_active: !this.state.is_action_menu_active,
selected_row_index: index
});
}
render() {
return <table className="ui unstackable celled very basic striped table unstackable_very_basic_striped_table">
<thead>
<tr>
<th>{Language.name}</th>
<th>{Language.role}</th>
<th>{Language.department}</th>
<th>{Language.action}</th>
</tr>
</thead>
<tbody>
{this.getTableRows()}
</tbody>
</table>
}
}
export default UnstackableVeryBasicStripedUsersTable;
Upvotes: 2