ReactJS: How to render columns horizontally - javascript

I am facing an issue to order the columns of a fetched API data horizontally. I am trying to print the data fetched from an API into a table. Anyhow the rows are well printed horizontally, but the function that I used for rows this.state.data.map() doesn't function in the same way for the columns. I think it's ES6 standard, but I am not sure. Here is my printed issue.
Here is my code sample:
class App extends React.Component
{
constructor()
{
super();
this.state = {
rows: [],
columns: []
}
}
componentDidMount()
{
fetch( "http://ickata.net/sag/api/staff/bonuses/" )
.then( function ( response )
{
return response.json();
} )
.then( data =>
{
this.setState( { rows: data.rows, columns: data.columns } );
} );
}
render()
{
return (
<div id="container" className="container">
<h1>Final Table with React JS</h1>
<table className="table">
<thead> {
this.state.columns.map(( column ) => (
<tr>
<th>{column[0]}</th>
<th>{column[1]}</th>
<th>{column[2]}</th>
<th>{column[3]}</th>
</tr>
) )}
</thead>
<tbody> {
this.state.rows.map(( row ) => (
<tr>
<td>{row[0]}</td>
<td>{row[1]}</td>
<td>{row[2]}</td>
<td>{row[3]}</td>
</tr>
) )
}
</tbody>
</table>
</div>
)
}
}
ReactDOM.render( <div id="container"><App /></div>, document.querySelector( 'body' ) );
I was able to print harcoded, if I give value to the 'th' elements, but I want to print it dynamically, in case the data within the API has been changed.
You are welcome to contribute directly to my Repo: Fetching API data into a table
Here is how looks like my example, when columns values has been hardcoded within 'th' elements.
Any suggestions will be appreciated!

var data = {
columns: [
"Full name",
"Job title",
"Age",
"Bonus",
],
rows: [
[
"John Smith",
"team lead front-end",
30,
444.08,
],
[
"Tom Jones",
"front-end developer",
25,
333.3,
],
[
"Deborah Barnes",
"front-end developer",
21,
233.66,
],
[
"Isaac Roberson",
"technical support",
44,
353,
],
[
"Josh Brown",
"team lead back-end",
35,
353,
],
[
"Chester Mckinney",
"back-end developer",
33,
223.27,
],
[
"Ora Burton",
"back-end developer",
32,
192.92,
],
[
"Jim Brown",
"technical support",
19,
98.99,
],
],
}
class App extends React.Component
{
constructor()
{
super();
this.state = {
rows: [],
columns: []
}
}
componentDidMount()
{
this.setState( { rows: data.rows, columns: data.columns } );
}
render()
{
return (
<div id="container" className="container">
<h1>Final Table with React JS</h1>
<table className="table">
<thead>
<tr>
{this.state.columns.map(( column, index ) => {
return (<th>{column}</th>)
}
)
}
</tr>
</thead>
<tbody> {
this.state.rows.map(( row ) => (
<tr>
<td>{row[0]}</td>
<td>{row[1]}</td>
<td>{row[2]}</td>
<td>{row[3]}</td>
</tr>
) )
}
</tbody>
</table>
</div>
)
}
}
ReactDOM.render( <div id="container"><App /></div>, document.querySelector( 'body' ) );
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
Hope it may help

Not sure why you wanted to do columns[0], [1], [2] and [3]. Each column inside the map is a string. If you do columns[0] it will return you the first character from that which is what is happening in your case. Full Name, Job title, Age Bonus are rendered in your first image. First four characters in your columns.
The key attribute I added is just React's requirement to provide unique keys and has nothing to do with the problem.
this.state.columns.map((column, index) => (
<tr>
<th key={"columns-" + index.toString()}>
{column}
</th>
</tr>
))

Related

Join multiple array maps in ReactJs

im new in reactjs, is that possible to do in reactjs,like mysql inner join, here my sample code.
{dataCustomer.map((customer) => (
<tr>
<td>{customer.custid}</td>
<td>{customer.custname}</td>
<td>{customer.mailingaddr}</td>
<td>{customer.stateid}</td>
<td>{customer.districtid}</td>
<td>{customer.postcode}</td>
</tr>
))}
{dataState.map((state) => (
<tr>
<td>{state.stateid}</td>
<td>{state.statename}</td>
</tr>
))}
how to join array map data from customer.stateid & state.stateid to call state.statename without use SQL syntax?..Is that possible?
This should work
let joinedData=[]
dataCustomer.forEach((customer)=>{
let st= dataState.filter((state)=>state.stateid===customer.stateid);
if(st.length>0)
joinedData.push({...customer,statename:st[0].statename})
})
joinedData array will now contain the customer objects with the corresponding statename and you can use it as
{joinedData.map((customer) => (
<tr>
<td>{customer.custid}</td>
<td>{customer.custname}</td>
<td>{customer.mailingaddr}</td>
<td>{customer.stateid}</td>
<td>{customer.districtid}</td>
<td>{customer.postcode}</td>
<td>{customer.statename}</td>
</tr>
))}
It is not exactly the same but I think the function below that I wrote can help you:
let customers = [{
name: "Foo",
stateid: 1
},
{
name: "Boo",
stateid: 3
},
{
name: "Goo",
stateid: 2
},
{
name: "Zoo",
stateid: 2
},
];
let states = [{
name: "State1",
id: 1
},
{
name: "State2",
id: 2
},
];
function join(customers, states, column1, column2) {
return customers.map(customer => {
states.forEach(state => {
if (customer[column1] === state[column2]) {
customer["state"] = { ...state };
}
})
return customer;
})
}
console.log(join(customers, states, "stateid", "id"))
Note that column1 and column2 parameters are the properties you are joining on.

Generate Multiple Tables From A Single Map React

I'm trying to generate six different React bootstrap tables based on the groupName field of the below data (more objects inside, just used three for example):
CompetitionData.js
const data= {
"players": [],
"teams": [
{
"id": 1,
"name": "England",
"groupName": 4
},
{
"id": 2,
"name": "Germany",
"groupName": 6
},
{
"id": 4,
"name": "Russia",
"groupName": 2
}
]
}
export default data;
Currently I'm able to map through the data and generate a single table, but not sure how to loop through the data just once in order to generate six different tables...
Standings.js
import React from "react";
import { Table } from "react-bootstrap";
import CompetitionData from "../data/CompetitionData";
export const Standings = () => {
const data = CompetitionData;
return (
<Table striped bordered hover size="sm" variant ="dark">
<thead>
<tr>
<td>Country</td>
<td>Group</td>
</tr>
</thead>
<tbody>
{data?.teams?.length
? data.teams.map((team, index) => (
<tr key={index}>
<td>{team.name}</td>
<td>{team.groupName}</td>
</tr>
))
: null}
</tbody>
</Table>
);
};
Any idea how to go about doing that?

Handling complex data objects with Reactjs

I am trying to create a table of orders. I work with React+Redux.
I have my data stored in props.
The data is structured similar to this: (a bit more detailed)
[{ //stored in props(redux state)
"id": 37, //order 1
"content": {
"items": {
"47427": {
"price": "12.49",
"format": "[\"1x12\"]",
"quantity": 1,
},
"23451": {
"price": "18.99",
"format": "[\"1x7\"]",
"quantity": 1,
},
}
},
"address": {
"first_name": "Tyrion",
"last_name": "Lannister",
"line1": "The Red Keep",
"city": "King's Landing",
"country": "Westeros",
}
}, {
"id": 38, //order 2
"content": {
"items": {
"183429": {
"price": "8.99",
"format": "[\"1x7\"]",
"quantity": "1",
}
}
},
"address": {
"first_name": "Arya",
"last_name": "Stark",
"line1": "23 Wolf st.",
"city": "Winterfell",
"country": "Westeros",
}
}, {
"id": 30, //order 3
"content": {
"items": {
"20399": {
"price": "21.99",
"format": "[\"1x12\"]",
"quantity": 1,
}
}
},
"address": {
"first_name": "Jon",
"last_name": "Snow",
"line1": "29 Winter is here st.",
"city": "The Wall",
"country": "Westeros",
}
}]
I want to access the "content" and "address" properties of each order and display it in a table. So i tried to call orders.map() on this object but this only gives me access to the first layer of properties - for instance order.id.
When i try to access order.content.item.price i get an error "can't read property of undefined".
My question goes on about order.content.items. that's when i have another object to iterate over since it has different property names, that contain properties inside them (.price, .format, .quantity).
So basically, how do i handle this complex data, so I can grab every piece of info in this object and place them in my table?
//my render function of <OrdersTable />
render() {
let filter = this.props.filter || {};
let orders = this.props.orders || [];
let content = orders.map(order => {
return (
<tr key={order.id}>
<td>{order.content}</td>
</tr>
)
})
let address = orders.map(order => {
return (
<tr key={order.id}>
<td>{order.address.first_name}</td>
</tr>
)
})
return (
<div>
<button className="filter"
onClick={this.props.showContent}>
Show Content
</button>
<button className="filter"
onClick={this.props.showAddress}>
Show Address
</button>
<table className='orders'>
<thead className={filter.showContent?'content': 'content hidden'}>
<tr>
<th>Items</th>
<th>Format</th>
<th>Quantity</th>
<th>Price</th>
</tr>
</thead>
<thead className={filter.showAddress?'address': 'address hidden'}>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Country</th>
<th>City</th>
</tr>
</thead>
<tbody className={filter.showContent?'content': 'content hidden'}>
{content}
</tbody>
<tbody className={filter.showAddress?'address': 'address hidden'}>
{address}
</tbody>
</table>
</div>
)
Thank you very much :)
EDIT:
So here's what did the trick in my case: (with the help of #TW80000 and #TomDavies)
let content = orders.map(order => {
const items= Object.keys(order.content.items).map(id => {
const item= order.content.items[id];
return(
<tr key={id}>
<td>{id}</td>
<td>{item.format}</td>
<td>{item.quantity}</td>
<td>{item.price}</td>
</tr>
)
})
return items;
});
const address = orders.map(order => {
return (
<tr key={order.id}>
<td>{order.address.first_name}</td>
<td>{order.address.last_name}</td>
<td>{order.address.country}</td>
<td>{order.address.state}</td>
<td>{order.address.city}</td>
<td>{order.address.line1}</td>
<td>{order.address.zip}</td>
</tr>
)
});
...
<tbody className={filter.showContent?'content': 'content hidden'}>
{content}
</tbody>
<tbody className={filter.showAddress?'address': 'address hidden'}>
{address}
</tbody>
Since you are working with complex data, I'd rather separate everything into small subcomponents so it get's easier to use and understand the code later.
// Only order details
const OrderRow = (order) => {
return (
<tr>
{
Object.keys(order.content.items).map((key, index) => {
const item = order.content.items[key]
return (
<td key={index}>{item.price} {item.format} {item.quantity}</td>
)
})
}
</tr>
)
}
// Only address details
const AddressRow = (address) => {
return (
<tr>
<td>{adress.first_name}</td>
</tr>
)
}
// In your main component, render them all
render() {
...
return (
<table>
...
<tbody>
{orders.map(order => <OrderRow key={order.id} order={order} />)}
</tbody>
<tbody>
{orders.map(order => <AddressRow key={order.id} address={order.address} />)}
</tbody>
</table>
)
}
I want to access the "content" and "adress" properties of each order and display it in a table.
You've spelled address wrong pretty much everywhere, that could be why it's not being read correctly.
So i tried to call orders.map() on this object but this only gives me access to the first layer of properties - for instance order.id.
That's not true, you will have access to all properties: id, address, and content.
When i try to access order.content.item.price i get an error "can't read property of undefined".
That's because it's content.items with an "s", not content.item like you have written. content.item is undefined and that's why you get this error.
My question goes on about order.content.items. that's when i have another object to iterate over since it has different property names, that contain properties inside them (.price, .format, .quantity).
You can do a nested loop. Example:
let content = orders.map(order => {
const tds = Object.keys(order.content.items).map(id => {
const item = order.content.items[id];
// You can use item.quality and item.format here as well
return(<td>{item.price}</td>);
})
return (
<tr key={order.id}>{tds}</tr>
);
})

React iterate props in JSX

I was new in React, and I am confusing about iterating props data in JSX.
Assume the this.props.data is
[
[
"2017-1",
{
title: "title1"
describe: "des1"
}
],
[
"2017-2",
{
title: "title2"
describe: "des2"
}
],...
]
How do I iterate data in table?
I was hoping it will render some kind of like this
<tbody>
<tr>
<td>2017-1</td>
<td>title1</td>
<td>des1</td>
</tr>
<tr>
<td>2017-2</td>
<td>title2</td>
<td>des2</td>
</tr>
...
</tbody>
I would map it. I'm assuming that the format will always be the same (out of laziness).
(Please do not run the snippet, it is only for formatting)
Fiddle: https://jsfiddle.net/gL8drpyd/1/
var data = [
[
"2017-1",
{
title: "title1"
describe: "des1"
}
],
[
"2017-2",
{
title: "title2"
describe: "des2"
}
]
];
let rows = data.map( (item) =>
(
<tr>
<td>{item[0]}</td>
<td>{item[1].title}</td>
<td>{item[1].describe}</td>
</tr>
)
);
// put this in the <tbody> in render
<tbody>
{rows}
</tbody>

React Multi Column Radio

I'm implementing a worker shift scheduler in React. See screenshot below
I receive the following employee object from the backend:
[{
"employeeId": "id",
"name": "bob"
},{
"employeeId": "id",
"name": "steve",
}]
I also receive the following shifts object from the backend:
"shifts": [
{
"shiftStart": "03:00",
"shiftEnd": "07:00"
},
{
"shiftStart": "16:00",
"shiftEnd": "24:00"
},
{
"shiftStart": "18:00",
"shiftEnd": "00:00"
},
{
"shiftStart": "12:10",
"shiftEnd": "17:10"
}
]
I'm using Radio component from ant-design. My code is the following:
class PlanningShiftManagement extends Component {
constructor(props) {
super(props);
this.state = {
employees: [],
shifts: [],
employeeshifts: []
}
this._populateTableData = this._populateTableData.bind(this)
this._handleChange = this._handleChange.bind(this)
}
_populateTableData(){
return this.state.employees.map((employee,index) => {
let employeecheckbox = this.state.shifts.map((shift) => {
return(
<RadioButton value={[`${shift.shiftStart}`, `${shift.shiftEnd}`, `${employee.key}`]} key={`${employee.title}-${shift.shiftStart}-${shift.shiftEnd}`}>{shift.shiftStart} - {shift.shiftEnd}</RadioButton>
)
});
return(
<tr key={employee.title}>
<td>{employee.title}</td>
<td>
<RadioGroup onChange={(e) => this.handleChange(e.target.value)}>
{employeecheckbox}
</RadioGroup>
</td>
</tr>
)
})
}
_handleChange() {
}
render() {
return(
<div>
<table>
<thead>
<tr>
<th>Employee Name</th>
<th>Shifts</th>
</tr>
</thead>
<tbody>
{this._populateTableData()}
</tbody>
</table>
</div>
);
}
Now, I'm struggli with how to work on the _handleChange() so that I can store the object in the employeeshifts state so I can send back to the backend.
[{
"shiftStart": "20170313 10:00",
"shiftEnd": "20170313 17:00",
"employeeId": "id"
},
{
"shiftStart": "20170313 10:00",
"shiftEnd": "20170313 17:00",
"employeeId": "id"
}]
Since each employee can only be assigned to one shift, it's a Radio element, so using .push() is not going to work.
You can pass employeeId to handleChange:
<RadioGroup onChange={(e) => this.handleChange(e.target.value, employee.id)}>
Shape your employeeshifts as a object:
{
"employeeId": {
"shiftStart": "20170313 10:00",
"shiftEnd": "20170313 17:00",
},
}
And transform employeeshifts to array before send to server.

Categories