Reputation: 13
I am creating a dynamic table using react based on objects.
The problem is that I am trying to render a new row for every three TD, but instead it is rendering all TDs in the same table row (tr).
How can I separate the TDs into az new TR after a group of 3 TDs have been filled?
Here is my code:
Component rendering table:
`export class Roster extends React.Component{
render(){
return(
<div id="tab">
<table >
<tbody>
<tr>
<td colSpan={3}>
<h4>Goalkeepers</h4>
</td>
</tr>
</tbody>
<Goalies/>
</div>
)
}
}`
Component looping through object:
`class Goalies extends React.Component{
getTable() {
let td_array = [];
let goal_object = {};
Object.keys(goalies).forEach(function(key) {
goal_object = (goalies[key]);
});
for(const checker in goal_object){
td_array.push(<td key={checker}>{goal_object[checker].p_name} <br/> {goal_object[checker].city} <br/> {goal_object[checker].number}</td>);
}
return(
<tr>
{td_array}
</tr>
)
}
render() {
return (<tbody>{this.getTable()}</tbody>)
}
}`
Objects:
export const def = { 1:{ p_name:"p1", number: 2, city: "city1" },
2:{
p_name:"p2",
number: 5,
city: "city2"
},
3:{
p_name:"p3",
number: 3,
city: "city3"
},
4:{
p_name:"p4",
number: 7,
city: "city4"
},
5:{
p_name:"p5",
number: 15,
city: "city5"
},
6:{
p_name:"p6",
number: 21,
city: "city6"
}
}
I want to get:
td1 | td2 | td3 |
---|---|---|
td4 | td5 | td6 |
instead, I am getting:
td1 | td2 | td3 | td4 | td5 | td6 |
---|
I tried using conditional statements, pushing into a new array...
Upvotes: 0
Views: 691
Reputation: 90217
In order to achieve the layout you're after, the correct HTML markup would look like this:
<table>
<thead>
<tr>
<th colspan="3">
<h4>Goalkeepers</h4>
</th>
</tr>
</thead>
<tbody>
<tr>
<td>td1</td>
<td>td2</td>
<td>td3</td>
</tr>
<tr>
<td>td4</td>
<td>td5</td>
<td>td6</td>
</tr>
</tbody>
</table>
First, you'll want to group your items into arrays of n
(3 in your case). I'd use a generator function:
function* toChunks(arr, n) {
for (let i = 0; i < arr.length; i += n) {
yield arr.slice(i, i + n)
}
}
const rows = [...toChunks(items, 3)]
As an alternative, you could also use:
const chunk = (arr, n) =>
[...Array.from({ length: Math.ceil(arr.length / n) }).keys()].map((key) =>
arr.slice(key * n, (key + 1) * n)
)
const rows = chunk(items, 3)
Given the above rows, your component would look like this:
const Goalies = ({ rows }) => (
<tbody>
{rows.map((row, rk) => (
<tr key={rk}>
{row.map((cell, ck) => (
<td key={ck}>{cell.number}</td>
))}
</tr>
))}
</tbody>
)
However, by looking at your data I think you shouldn't be using a <table>
here at all. The layout you're after could easier be achieved with:
const Cells = ({ items }) => (
<div className="myWrapper">
{items.map((item, key) => (
<div key={key}>{item.number}</div>
))}
</div>
)
along with any of the following CSS models:
.myWrapper {
display: flex;
flex-wrap: wrap;
}
.myWrapper > * {
width: calc(100%/3)
}
/* or alternatively: */
.myWrapper {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr))
}
Upvotes: 0