React/preact OnClick <td> render table with details - javascript

I have a Table which when you click a td tag that is an plusbutton it should show the details about that row. Something like this:
Right now I am just testing it like this:
props.info.map((l, i) => {
return (
<tr>
<td>{i + 1}</td>
<td>{l.UserId}</td>
<td onClick={props.onShowInfoDetails}>
<MenuPlusButton /></td>
{props.showInfoDetails && (
<DetailsTable />
)
}
</tr>
)
})
where the DetailsTable is the thing i want to render onClick
export const DetailsTable = (props: Props) => {
return (
<tr>
<td>Hello</td>
</tr>
)
}
There is two problems with this. First the DetailsTable renders to the right of the rest of the content and not under it like in the picture. second problem is that when I click it all table rows show the hello not just the one that I clicked. Both of these I can't seem to figure out. The second problem I guess is because it says if props.showEntryDetails is true it renders the DetailsTable and the onClick sets it to true but how do I make it so it's only true for that row that I clicked?

Related

Data does not display right in table

I'm trying to display data in the table, but for some reasons appears empty fields. I think the issue is that firstly is looking deaths - fills the elements and cases becomes empty. Tried to do in many different ways. In some ways all data are just pulled in one column, in other ways the data just go in rows. Tryied to use lodash as well.
Current code:
<table className="table">
<tr>
<th>Cases</th>
<th>Deaths</th>
</tr>
{_.map(countryData, (item, key) => {
if (item.indicator === "cases") {
return (
<tr>
<td>{item.weekly_count}</td>
<td></td>
</tr>
);
} else {
return (
<tr>
<td>{item.weekly_count}</td>
</tr>
);
}
})}
</table>
Also tried in this way(still empty fields):
{countryData.map((value, key) => {
return (
<tr>
<td>
{value.indicator === "cases" ? value.weekly_count : null}
</td>
<td>
{value.indicator === "deaths" ? value.weekly_count : null}
</td>
</tr>
);
})}
My data from console.log:
Data
Expected result: expected result
Example of issue: Issue
countryData: This data comes after selecting the specific country
The map function is working just fine. The problem is with the object countryData. The object currently does not contain an array. Please make sure the object looks like:
countryData = [{indicator:"cases", weekly_count: xx}, {indicator:"deaths", weekly_count: yy}.....]
I have only used two fields inside each object, you may add more objects according to your requirement.
In order to view cases and deaths as separate columns, please add an empty cell before displaying "deaths".
{_.map(countryData, (item, key) => {
if (item.indicator === "cases") {
return (
<tr>
<td>{item.weekly_count}</td>
<td></td>
</tr>
);
} else {
return (
<tr>
<td></td>
<td>{item.weekly_count}</td>
</tr>
);
}
})}

How to handle event bubbling in Javascript

I implemented a toggle button for a list of items. To display the items and the toggle button, I run them through a loop given below.
renderRowValue = (values) => {
const sourceId = values.id;
const payload = {id: values.id, isActive: !values.isActive };
return (
<tr>
<td key = {sourceId}>
{values.name}
</td>
<td>
<SwitchToggleButton
onChange={this.handleToggleChange(payload)}
defaultChecked={values.isActive}
label={"version2"}
/>
</td>
</tr>
)
};
Then I call the function to display the value in the renderRowValue like this below:
<Grid xs={12} sm={12} md={10} className="shadow-border">
<Row>
<Table striped bordered hover>
<thead>
<tr>
<th>Source</th>
</tr>
</thead>
<tbody>
{values.map(this.renderRowValue)}
</tbody>
</Table>
</Row>
</Grid>
But the main issue is that when I toggle a button on the value of the others changes.For example, I turn the first item on, then everything else turns on automatically, the same for when I turn it off.
The function to handle toggle switch can be found below:
handleToggleChange =(values) => {
this.props.dispatch(values.isActive(values));
};
Please how can I fix this issue to just turn it on for the first item without affecting the rest?
assuming the handleToggleChange is in the same class as your component.
Update it so that it's a closure
handleToggleChange = (payload) = (e) => {
e.preventDefault()
this.props.dispatch(values.isActive(payload));
};
// renderRowValue
<SwitchToggleButton
onChange={this.handleToggleChange(payload)}
defaultChecked={values.isActive}
label={"version2"}
/>
This is how I've done it trying to stick as close to your code as possible without actually seeing all of your code.
https://gist.github.com/leslie-alldridge/5ffd25cfbd48c3134495b2245aa9d7ad

How to give unique id to table rows in react

I need to give different IDs to table rows, so that when I click on the first row, it'll show "selectedRow: 1" on console. Click on the second row, it'll show "selectedRow: 2"
Thanks in advance!
Here's my code:
<tbody>
{this.testData.map((item, i) => {
return (
<tr onClick={this.handler} key={i} >
<td>{item.name}</td>
<td>{item.age}</td>
<td>{item.address}</td>
</tr>
);
})}
</tbody>
handler=(e)=>{
let selectedRow = e.target.id //doesn't work
console.log("selectedRow:", selectedRow)
}
For that to work you would need to give every tr an id attribute, but it would be better if you just straight up pass that id to the function, like so:
<tr onClick={() => this.handler(item.id)}>
You can also use the index if the items don't have unique IDs.
Now the handler function would receive the id as an argument:
handler = (selectedRow) => {
console.log("selectedRow:", selectedRow)
}
For the tr onClick we can give our id as we like like <tr onClick={this.handler(item.id)}>
and our handler function will be high level function like below, then we don't require to create function each time
handler = id => e => {
console.log(id)
}
Sample code code from sandbox

react.js how to get prop form tree element

I am trying to make table cell editable after clicking on icon in another cell , for that I need to get index of element so the editor will open in the correct row , which icon belongs to.
My issue is that I dont know the way i should get the prop value of table DOM element here is code for for clearify
a part of dom tree generated with react:
<tbody>
{stepsDone.map(function(step,idx) {
let content = step;
const editing = this.state.editing;
if(editing){
content = (
<form onSubmit={this._save}>
<input type="text" defaultValue={step} />
</form>
);
}
return(
<tr key={idx}>
<td className="step" data-step={'step'+idx}>{content}</td>
<td className="icRow">
<Icon className="edit" onClick={this._showEditor} rownum={idx}/>
<Icon className="remove"/>
<Icon className="trash outline"/>
</td>
</tr>
)
},this)}
show editor function:
_showEditor(e){
this.setState({
editing:{
row:e.target.rownum
}
});
console.log(this.state.editing);
}
After execution of showedtior function console logs :
first click = null , which is normal i think
more clicks = undefined , and thats whats brings a trouble i want to receive idx from map function.
here is code from Icon.js
import React from 'react';
import classNames from 'classnames';
export function Icon(props) {
const cssclasses = classNames('icon', props.className);
return <i className={cssclasses} onClick={props.onClick}/>;
}
if you want to reveive the idx from the map function you should pass it to the function _showEditor so your code must be like this :
<Icon className="edit" onClick={this._showEditor(idx)}/>
and the function definition should be :
_showEditor = (idx) => (event) => {
this.setState({
editing:{
row:idx
}
});
console.log(this.state.editing);
}
or if you don't want to use the arrow functions for some reason, just replace
onClick={this._showEditor(idx)}
with
onClick={this._showEditor.bind(this,idx)}
and its definition becomes
_showEditor(idx){...}

Render 2 table rows in ReactJS

I want to achieve expandable row functionality for table.
Let's assume we have table with task names and task complexity. When you click on one task the description of task is shown below. I try to do it this way with ReactJS (in render method):
if (selectedTask === task.id) {
return [
<tr>
<td>{task.name}</td>
<td>{task.complexity}</td>
</tr>,
<tr>
<td colSpan="2">{task.description}</td>
</tr>
];
} else {
return <tr>
<td>{task.name}</td>
<td>{task.complexity}</td>
</tr>;
}
And it doesn't work. It says:
A valid ReactComponent must be returned. You may have returned undefined, an array or some other invalid object
I tried also to wrap 2 rows in a div but I get wrong rendering.
Please, suggest correct solution.
The render() method on a React component must always return a single element. No exceptions.
In your case, I would suggest wrapping everything inside a tbody element. You can have as many of those as you want in a table without disrupting your row structure, and then you'll always return one element inside render().
if (selectedTask === task.id) {
return (
<tbody>
<tr>
<td>{task.name}</td>
<td>{task.complexity}</td>
</tr>,
<tr>
<td colSpan="2">{task.description}</td>
</tr>
</tbody>
);
} else {
return (
<tbody>
<tr>
<td>{task.name}</td>
<td>{task.complexity}</td>
</tr>
</tbody>
);
}

Categories

Resources