React.js - Cant display array object in table - javascript

I cant display array object in map function. Could someone please tell me why ? When Im trying to display this object in the console I see it correctly.
class ProductsGrid extends React.Component {
constructor(props) {
super(props);
}
render() {
return (<Table striped bordered condensed hover>
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>Description</th>
<th>Url</th>
</tr>
</thead>
<tbody>
{this.props.products !== null ?
JSON.parse(this.props.products).map((product, index) => {
<tr>
{console.log(product.IdProduct)}
<td>{product.IdProduct}</td>
<td>{product.Name}</td>
<td>{product.Description}</td>
<td>{product.UrlFriendlyName}</td>
</tr>
}) : <tr><td></td><td></td><td></td><td></td></tr>}
</tbody>
</Table>);
}}

Your map function needs a return statement.

Related

React Array.map not populating table [duplicate]

This question already has an answer here:
List elements not rendering in React [duplicate]
(1 answer)
Closed 23 days ago.
I have a react component that is supposed to take an array of items passed to the component as a prop and render a table. I have done this successfully with another component already. Yet for some reason, the table does not want to populate rows in this component.
Here is the component that renders the :
class OrderList extends React.Component {
constructor(props) {
super(props);
this.populateTable = this.populateTable.bind(this);
}
populateTable() {
return this.props.orders.map((order) => {
<tr key={order.id}>
<td>{order.orderNo}</td>
<td>{order.customer.name}</td>
<td>{order.customerPO}</td>
<td>{order.orderDate}</td>
<td>{order.shipDate}</td>
</tr>
});
}
render() {
return(
<Table striped bordered hover>
<thead>
<tr>
<td>Order No.</td>
<td>Customer Name</td>
<td>Customer P.O.</td>
<td>Order Date</td>
<td>Ship Date</td>
</tr>
</thead>
<tbody>
{this.populateTable()}
</tbody>
</Table>
);
}
}
Using react dev tools, I can see that the orders prop does contain the correct data, and array of objects. I can even throw in a console.log line within the forEach loop, so I know the component is actually looping over the data. However, no rows are rendered?
Your map is not returning anything this is the reason
class OrderList extends React.Component {
constructor(props) {
super(props);
this.populateTable = this.populateTable.bind(this);
}
populateTable() {
return this.props.orders.map((order) => (
<tr key={order.id}>
<td>{order.orderNo}</td>
<td>{order.customer.name}</td>
<td>{order.customerPO}</td>
<td>{order.orderDate}</td>
<td>{order.shipDate}</td>
</tr>
));
}
render() {
return(
<Table striped bordered hover>
<thead>
<tr>
<td>Order No.</td>
<td>Customer Name</td>
<td>Customer P.O.</td>
<td>Order Date</td>
<td>Ship Date</td>
</tr>
</thead>
<tbody>
{this.populateTable()}
</tbody>
</Table>
);
}
}
when you use curly braces in map you have to use return keyword to return anything
in order to return from your method you can try something like this
populateTable() {
return this.props.orders.map((order) => {
return (<tr key={order.id}>
<td>{order.orderNo}</td>
<td>{order.customer.name}</td>
<td>{order.customerPO}</td>
<td>{order.orderDate}</td>
<td>{order.shipDate}</td>
</tr>)
});
}

how do I fix my code in order to display one table?

I am trying to render my dynamic JSON , but I am getting a table per result when it should be rendered in the same table.. what's happening this? my dummy array is a model from my backend api
const arr = [
{
"Demo": [
{
"_id": "T08210",
"name": "tilehaha",
"tags": [
"Demo"
],
"queries": [],
"urls": [],
"max_leght": [],
"count_items": []
},
],
}
];
export default function Demo() {
return (
<div>
{arr.map(obj =>
Object.entries(obj).map(([key, value]) => (
<table class="table">
<thead>
<tr key={key}>
<th scope="col">{key}</th>
</tr>
</thead>
<tbody>
<tr>
<td>{value.activityType}</td>
<td>{value.durationInSeconds}</td>
</tr>
</tbody>
</table>
)))}
</div>
);
}
I need to place in the blue section as heading 2671161009, and 2671161249 , and their child items as the following
Try this.
<table class="table">
<thead>
<tr>
{arr.map(obj => Object.entries(obj).map(([key, value]) => (
<th scope="col">{key}</th>
)))}
</tr>
</thead>
<tbody>
{arr.map(obj => Object.entries(obj).map(([key, value]) => (
<tr>
<td>{value.activityType}</td>
<td>{value.durationInSeconds}</td>
</tr>
)))}
</tbody>
</table>
Based on your comments, it seems like maybe this is what you want:
Note to future views -- now not applicable to the changed question:
const modArray = Object.keys(arr[0]).map(i => {
return {id: i, ...arr[0][i]}
});
const rowKeys = Object.keys(modArray[0]).filter(i => i !== "id")
export default function Demo() {
return (
<div>
<table class="table">
<thead>
<tr>
{modArray.map(i => <th key={i.id}>{i.id}</th>)}
</tr>
</thead>
<tbody>
<tr>
{modArray.map(item => <td key={item.id}>{item.activityType}</td>)}
</tr>
<tr>
{modArray.map(item => <td key={item.id}>{item.durationInSeconds}</td>)}
</tr>
{/* Or, do it dynamically */}
{rowKeys.map(rowKey => <tr key={rowKey}>
{modArray.map(item => <td key={item.id}>{item[rowKey]}</td>)}
</tr>)}
</tbody>
</table>
</div>
);
}
Note that at the top of that code sample, I transformed your input into a more usable format. Your beginning arr, for example, was an array of just 1 object, which had multiple keys, which really seemed to be the array you wanted to iterate over.
Hopefully this is at least close to what you're looking for.
Update 2, based on your changed question:
export default function Demo() {
return (
<div>
<table className="table">
<thead>
<tr>
{arr[0]["Demo"].map(i => <th key={i._id}>{i._id}</th>)}
</tr>
</thead>
<tbody>
<tr>
{arr[0]["Demo"].map(item => <td key={item._id}>{item.name}</td>)}
</tr>
</tbody>
</table>
</div>
);
}
The issue is here:
{arr.map(obj =>
Object.entries(obj).map(([key, value]) => (
<table class="table">
here you have put the entire table inside the loop instead of putting a single table row. So on every iteration it generates a new table. To resolve this issue, try this:
Try this:
<table class="table">
<thead>
<tr>
<th scope="col">Heading 1</th>
<th scope="col">Heading 2</th>
</tr>
</thead>
<tbody>
{
arr.map(obj =>
Object.entries(obj).map(([key, value]) => (
<tr>
<td>{value.activityType}</td>
<td>{value.durationInSeconds}</td>
</tr>
)))}
</tbody>
</table>

Making a table with a checkbox that updates table values in React

I'm unfamiliar with React and would appreciate some help. I have a table within a form where each row is a project that has a status (either 'Pending Approval' or 'Approved'). I also have a checkbox in each row. I would like it so that when the checkbox next to a row is selected and the form is submitted, I can change the status of each selected project to 'Approved.'
<Form>
<FormGroup>
<Button type="submit" onClick {this.submitClicked}>Approve Projects</Button>
</FormGroup>
<Table bordered={true}>
<thead>
<tr>
<th>Select</th>
<th>Project Name</th>
<th>Project Number</th>
<th>Project Status</th>
<th>Min Size</th>
<th>Max Size</th>
</tr>
</thead>
<tbody>
{projects.map((project: Project) =>
<tr key={project.projectNumber}>
<td>
<FormControl
type="checkbox"
id="selected"
value={project.projectName}
onChange={e => this.handleChange(e)}
/>
</td>
<td>{project.projectName}</td>
<td>{project.projectNumber}</td>
<td>{project.status}</td>
<td>{project.minSize}</td>
<td>{project.maxSize}</td>
</tr>
)}
</tbody>
</Table>
</Form>
What should go in my handleChange function and how should I go about doing this? I was wondering if there was some way to add the selected projects to an array and then change their status value?
You can use components with state. That allows you to manage a state inside a component. Thus you can manipulate it and change the projects' statuses in your example. More about this here: state classes
Example:
class YourComponent extends React.Component {
constructor(props) {
super(props);
this.state = {projects: props.projects};
}
handleChange = (e) => {
let projects = this.state.projects;
// manipulate your project here
this.setState({
projects: projects
});
}
render(){
return (<Form>
(...)
</Form>)
}
}

Communicating beteween parent and child with row ReactJs

I try to call a parent function from a child function.
I follow this example :Expose Component Functions but with this code my page does not load and my console is empty so i do not know find the problem.
I use webpack with babel and webpack-dev-server
Thank you for your answers.
I am sorry for my english.
class Row extends React.Component {
render(){
return(
<tr className="animated slideInRight">
<th scope="row">{this.props.data.ville_id}</th>
<td>{this.props.data.ville_nom}</td>
<td>{this.props.data.ville_nom_reel}</td>
<td>{this.props.data.ville_canton}</td>
<td><button className="btn btn-success" onClick={this.props.onClick} >Full Detail</button></td>
</tr>
)
}
}
export default class Metier extends React.Component {
constructor() {
super();
this.state = {
data: [],
};
}
deleteClick(e){
console.log("ici")
}
render(){
return(
<table className="table table-striped">
<thead>
<tr>
<th>IdVille</th>
<th>First Name</th>
<th>Last Name</th>
<th>Username</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{this.state.data.map(function(result,i){
var boundClick = this.deleteClick.bind(this,i)
return(
<Row onClick={boundClick} key={i} data={result} />
)
})}
</tbody>
</table>
)
}
}
You have to use the arrow function in the map so you can access this:
{this.state.data.map((result,i) => {
var boundClick = this.deleteClick.bind(this,i)
return(
<Row onClick={boundClick} key={i} data={result} />
)
})}
By using a simple function you create a new context and in that function you cannot access this.deleteClick. Using an arrow function you can still access it.

How to specify class on a JSX node?

I have defined a class name for the table below (as part of JSX).
<table class="table">
However once its displayed the class is not set on the table:
var SearchResult = React.createClass({
render: function(){
return (
<table class="table">
<thead>
<tr>
<th>Name</th>
<th>Address</th>
</tr>
</thead>
<tbody>...</tbody>
</table>
);
}
});
Instead the table shows as <table data-reactid=".0.1.0.0">...</table> in Chrome -> inspect element.
ReactJS uses the attribute className to avoid the use of a JavaScript reserved word.
<table className="table">

Categories