I have a slightly strange problem that i cant solve. I have to render a table using react - however my data structure is such that i need the name from the first level to be the table headings - I then need to map the data associated to that heading into the correct cells in the table.
Here is my data
[{
"cell_id": 1,
"step_data": [{
"width": 1920,
"name": "bruce",
}, {
"width": 2236,
"name": "ben",
}],
"cell_name": " boys names"
},
{
"cell_id": 2,
"step_data": [{
"width": 1920,
"name": "grace",
}, {
"width": 2236,
"name": "megan",
}],
"cell_name": "girls names"
}
To map the table headings i do this which dynamically renders the headings however I cant seem to put the data under the correct headings as they all go on the same row.
Any ideas how i do this?
My desired task is to have a table with two headings boys names and girls names - I need the step_data from boys names to be rows under the boys name heading and the step data from girls names to be under the girls names heading
<table className="table">
<tbody>
<tr>
{this.props.data.map((item, key) => <th key={key}>{item.cell_name}</th>
)}
</tr>
{this.props.data.map(data => data.map((z, key) => <td key={key}>{z.name}</td>))}
<tr>
</tr>
</tbody>
</table>
{[
...Array( // get the number of rows you need to create
Math.max(...this.props.data.map(({ step_data }) => step_data.length))
).keys()
].map(i => (
<tr key={i}>
{this.props.data.map(({ step_data, cell_name }) => (
<td key={cell_name}>{(step_data[i] || {}).name}</td>
))}
</tr>
))}
Related
I have a JavaScript object in which I am trying to render as a table, though I am unable to figure out how to access each individual array.
Here is a sample of the object (defLogTable):
{
"headings": [
"Item",
"Equip Tag",
"Ref#",
"Description",
"Corrective Action Taken or Date Completed"
],
"values": [
[
1,
"RTU-1",
1,
"This did not work",
"Make it Work"
],
[
2,
"EF-1",
2,
"This also didn't work",
"Make this one work too"
]
]
}
Each 'values' array corresponds to a row in the table.
And What I have tried:
<table className="def-tbl">
<tbody>
{console.log(defLogTable)}
{defLogTable.headings.map(heading => (
<th>{heading}</th>
))}
</tbody>
</table>
Error: TypeError: Cannot read properties of undefined (reading 'headings')
Any help is appreciated!!
Use a nested map to render each row in the values property.
<table className="def-tbl">
<thead>
<tr>
{defLogTable.headings.map(heading => (
<th>{heading}</th>
))}
</tr>
</thead>
<tbody>
{defLogTable.values.map(row => (
<tr>
{row.map(cell => (
<td>{cell}</td>
))}
</tr>
))}
</tbody>
</table>
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?
I'm having trouble with displaying my json data correctly. I want to get each products and place them into it's own row.
The problem now is that it places all the data of for example the value "name" into one table row instead of multiple rows.
This is my json data
{
id: "FVFkkD7s8xNdDgh3zAyd",
name: "AlperKaffe",
products: [
{
id: "0cfBnXTijpJRu14DVfbI",
name: "Første Kaffe",
price: "1",
size: "small",
quantity: "20 ml"
},
{
id: "JQadhkpn0AJd0NRnnWUF",
name: "Anden Kaffe",
price: "2",
size: "Medium",
quantity: "25 ml"
},
{
id: "UwHHdH8bFxbVHkDryeGC",
name: "kaffeeen",
price: "300",
size: "Small",
quantity: "23 ml"
},
{
id: "WiX5h0wFMNkCux9cINYq",
name: "kaffe modal",
price: "230",
size: "Medium",
quantity: "39 ml"
},
this is my Js file which gets the json data. As you can see i'm only working with the "name" value for now
// Jquery getting our json order data from API
$.get("http://localhost:8888/products", (data) => {
let rows = data.map(item => {
let $clone = $('#frontpage_new_ordertable tfoot tr').clone();
let productsName = item.products.map(prod => `${prod.name}`);
$clone.find('.name').html(productsName);
return $clone;
});
// appends to our frontpage html
$("#frontpage_new_ordertable tbody").append(rows);
});
this is my html file
<body>
<table id="frontpage_new_ordertable">
<tbody>
<tr>
<th>Name</th>
<th>Price</th>
<th>Size</th>
<th>Quantity</th>
<th></th>
</tr>
</tbody>
<tfoot>
<tr>
<td class="name"></td>
<td class="price"></td>
<td class="size"></td>
<td class="quantity"></td>
<td class="buttons"></td>
</tr>
</tfoot>
</table>
<script src="./itemPage.js"></script>
</body>
you must replace
let rows = data.map(item => {
to
let rows = data.products.map(item => {
and
let productsName = item.products.map(prod => `${prod.name}`);
to
let productsName = item.name;
https://jsfiddle.net/ab7t1vmf/3/
The issue in your JS snippet seems to be let rows = data.map(item => { ...
From what you describe, the JSON data is comprised of 3 keys:
id
name
products
You cannot execute a map function directly on a Javascript Object, this function requires an array.
Looking a bit more at your code, I understand you need to display each product on its own row. Thus, you would need to use the map function on data.products which contains an array (of products).
let rows = data.products.map(item => {
// ...
$clone.find('.name').html(item.name);
// ...
// ...
});
Reference: https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/Array/map
I am using table for showing the datas and for data I am using Api.
Api data looks like::
{
"data": [
{
"id": "1",
"name": "name1",
"label": "label1"
},
{
"id": "2",
"name": "name2",
"label": "label2"
},
{
"id": "3",
"name": "name3",
"label": "label3"
}
]
}
html code
<table class="table table-striped">
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>Label</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let data of sample;">
<td>{{data.id}}</td>
<td>{{data.name}}</td>
<td>{{data.label}}</td>
<tr>
<tbody>
<table>
I need the 10 table rows statically(fixed). The table data is from API. For exanple ,Api contains 2 data... Then UI table should be with 2 rows of data and balance with emply rows... but there should display 10 rows(Mandatory)
which means in UI i want 10 rows with data from Api and balance should be empty.
You can fix in view layer, ts layer or even backend API layer (Not really recommended).
In view layer if you loop over your data, you can calculate if your data's size goes over arbitrary threshold and if not loop again to display as many empty rows as possible.
In ts layer, when you receive data from api you can modify variable you pass to your view by adding to an array as many empty items as you need.
What's important if you use null, then you have to check for it with for example elvis operator.
I would advise agains adding to an array an object with all properties set to null, because then these are not so easily distinguishable from valid data from API and you can for instance make some rows interactive, even though they should not be.
const dataFromApi = [{ "id": "1", "name": "name1" }, { "id": "2", "name": "name2" }]
const minRowsNumber = 10;
const diff = minRowsNumber - dataFromApi.length;
const viewTableData = diff > 0 ? dataFromApi.concat(new Array(diff).fill(null)) : dataFromApi;
console.log(viewTableData)
Example in AngularJs (No Angular in SO Snippets, but it is the same principle)
angular.module('example', [])
.controller('ExampleController', function ExampleController() {
const dataFromApi = [{ "id": "1", "name": "name1" }, { "id": "2", "name": "name2" }]
const minRowsNumber = 10;
const diff = minRowsNumber - dataFromApi.length;
this.viewTableData = diff > 0 ? dataFromApi.concat(new Array(diff).fill(null)) : dataFromApi;
});
table {
border-collapse: collapse;
}
td, th {
border: 1px solid black
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<div ng-app="example" ng-controller="ExampleController as example">
<table>
<thead>
<tr>
<th>Id</th>
<th>Name</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in example.viewTableData track by $index">
<td>{{row ? row.id : ' '}}</td>
<td>{{row ? row.name : ' '}}</td>
</tr>
</tbody>
</table>
</div>
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>
);
})