How to make sub table <tr> of parent table <tr>? - reactjs

I know that maybe this question can be confusing for you, but I will try to explain in more detail.
First: I have this api
{
"data": [
{
"id": 1,
"title": "Действие 1",
"subactions": [
{
"id": 2,
"title": "Субдействие 1",
"status": {
"id": 1,
"text": "Выполнено"
},
"countries": [
"kz",
"kg"
],
"theme": {
"id": 1,
"text": "Изменение климата"
},
"characteristics": {
"0": "Другие действия",
"id": 1
},
"monthes": [
{
"month": 1,
"year": 2017,
"complete": 0
},
{
"month": 2,
"year": 2017,
"complete": 1
},
{
"month": 3,
"year": 2017,
"complete": 1
},
{
"month": 4,
"year": 2017,
"complete": 1
},
{
"month": 5,
"year": 2017,
"complete": 1
},
{
"month": 1,
"year": 2018,
"complete": 0
},
{
"month": 2,
"year": 2018,
"complete": 0
}
]
}
]
}
The second: the table should look like in this picture
The third: The problem is that I don not know how to loop <tr> as child of another <tr> parent.
The Fourth: This my attempts of doing that
{
task.map((value, i) => {
if(value.subactions !== undefined){
return (
value.subactions.map((subaction, i) => {
return (
<div>
{/*Parent tr*/}
<tr key={i}>
<td>{value.id}</td>
<td>{value.title}</td>
</tr>
{/* end Parent tr*/}
{/*sub table of parent tr*/}
<tr key={i}>
<td>{subaction.id}</td>
<td>{subaction.title}</td>
<td>{subaction.status.text}</td>
<td>
{subaction.countries.map((country, i) => {
return (
i == subaction.countries.length - 1 ?
<span key={i}>{country} </span> :
<span key={i}> {country},</span>
)
})
}
</td>
<td></td>
<td>{subaction.theme.text}</td>
<td>{subaction.characteristics[0]}</td>
{subaction.monthes.map((month, i) => {
return (
month.complete ?
<td className='task-month task-end'>
<input
type="checkbox"
className="css-checkbox lrg"/>
<label htmlFor="checkbox69" name="checkbox69_lbl"
className="css-label lrg vlad"/>
</td> : <td></td>
)
})
}
</tr>
{/*end sub table of parent tr*/}
</div>
)
})
)
} else {
return undefined
}
})
}
Please, anyone help to point out of my mistakes.

Replace div tag to table tag and In you parent table at second td use colspan="(total number of td in your second tr) - 2"
check below changes , I have mentioned the colspan count :
task.map((value, i) => {
if(value.subactions !== undefined){
return (
value.subactions.map((subaction, i) => {
return (
<table>
{/*Parent tr*/}
<tr key={i}>
<td>{value.id}</td>
<td colspan="1+totalContriesCount+2+totalMonthsCount">{value.title}</td>
</tr>
{/* end Parent tr*/}
{/*sub table of parent tr*/}
<tr key={i}>
<td>{subaction.id}</td>
<td>{subaction.title}</td>
<td>{subaction.status.text}</td>
<td>
{subaction.countries.map((country, i) => {
return (
i == subaction.countries.length - 1 ?
<span key={i}>{country} </span> :
<span key={i}> {country},</span>
)
})
}
</td>
<td></td>
<td>{subaction.theme.text}</td>
<td>{subaction.characteristics[0]}</td>
{subaction.monthes.map((month, i) => {
return (
month.complete ?
<td className='task-month task-end'>
<input
type="checkbox"
className="css-checkbox lrg"/>
<label htmlFor="checkbox69" name="checkbox69_lbl"
className="css-label lrg vlad"/>
</td> : <td></td>
)
})
}
</tr>
{/*end sub table of parent tr*/}
</table>
)
})
)
} else {
return undefined
}
})
}

Try making the parent row span to the maximum so you might achieve the output
<tr>
<td rowspan="maxRowCount"></td>
<td colspan="1"></td>
</tr>

Related

How to call nested object list on table list

Hi im newbie on react js,
how to call nested object(array/list) on main object, i mean object in object
<tbody>
{
vehicles.map((v, index) =>(
<tr key={v.id}>
<td>{index +1}</td>
<td>{v.type}</td>
<td>{v.plateNumber}</td>
{v.employee.map(item => {
return (
<td>
<ul>{item.name}</ul>
</td>
);
})}
<td>
<Link className="btn btn-info" to={`/vehicles/edit/${v.id}`}>Update</Link>
<button className="btn btn-danger ml-2" onClick={() => {deleteSweetAlert(v.id)}}>Delete</button>
</td>
</tr>
))
}
</tbody>
This one my JSON example
[
{
"id": 1,
"type": "MasterCard",
"plateNumber": "3747948",
"status": "1",
"employee": {
"id": 1,
"name": "Joanne Hagenes Sr.",
"location": "60794 Rippin Cove Suite 080\nTroyberg, ND 95778",
"department": "Wuckert-Luettgen",
"status": "1"
}
}
]
I always get this error message at the console
react-dom.development.js:26874 Uncaught TypeError: v.employee.map is not a function
map() function can only applied with an array, so in your case employee should be an array instead an object:
{
"id": 1,
"type": "MasterCard",
"plateNumber": "3747948",
"status": "1",
"employee": [{
"id": 1,
"name": "Joanne Hagenes Sr.",
"location": "60794 Rippin Cove Suite 080\nTroyberg, ND 95778",
"department": "Wuckert-Luettgen",
"status": "1"
}]
}
Another way to fix this, since each of your vehicle contains only 1 employee (based on how u named it). So i suppose you dont need to use map() function in this case:
<tbody>
{
vehicles.map((v, index) =>(
<tr key={v.id}>
<td>{index +1}</td>
<td>{v.type}</td>
<td>{v.plateNumber}</td>
<td>
<ul>{item.name}</ul>
</td>
<td>
<Link className="btn btn-info" to={`/vehicles/edit/${v.id}`}>Update</Link>
<button className="btn btn-danger ml-2" onClick={() => {deleteSweetAlert(v.id)}}>Delete</button>
</td>
</tr>
))
}
</tbody>
You can use interface to define.
interface IFoo {
foo: string;
}
interface IBaz {
baz: string;
foo: IFoo;
}
const obj: IBaz = {
baz: 'bar',
foo: {
foo: 'foo',
},
};
console.log(obj.baz); // -> baz
console.log(obj.foo.foo); // -> foo

In case of "null" or "undefined" dont display the table in react js

here is the code which displaying the all the data i have to put check if body contains nulll then dont display table.Currently it displaying the empty table.but that empty table shouldnt be visible.any help would be apprecited
{logs &&
logs.map((log) => {
if (
log.body === "null" ||
log.body === "undefined" ||
log.body === ""
) {
console.log("empty body");
} else {
return (
<Table striped bordered hover>
<thead>
<tr>
<th>Parameter</th>
<th>
Value <CButton onClick={handleShow}>View</CButton>
</th>
</tr>
</thead>
<tbody>
{log.body &&
Object.keys(log.body).map((key) => (
<tr key={key}>
<td>{key}</td>
<td>{JSON.stringify(log.body[key])}</td>
</tr>
))}
</tbody>
</Table>
);
}
})}
And here is the API.
[
{
"id": 1,
"body": {
"buy_WBNB": 0.1231,
"sell_WBNB": 0.1541,
"expected_profit": -42.27542384981283,
},
"response": "CONNECTION ERROR: The connection got closed with the close code `4040`",
"created_at": "Feb 28, 2022 11:57 AM"
},
{
"id": 2011,
"body": null,
"response": "connection not open on send()",
"created_at": "Feb 28, 2022 5:49 PM"
},
]
check first log.body exist
{logs &&
logs.map((log) =>
log.body && Object.keys(log.body).map((key) => (
<tr key={key}>
<td>{key}</td>
<td>{JSON.stringify(log.body[key])}</td>
</tr>
))
)}
output will look like:

Mapping an array in react, descending order

I want to use the following data
[
{
"id": "1",
"label": "Score",
"tabledata": [
{"label": "Day 1", "data": {"score": 73}},
{"label": "Day 2", "data": {"score": 64}},
{"label": "Day 3", "data": {"score": 72}}
]
}, {
"id": "2",
"label": "Success",
"tabledata": [
{"label": "Day 1", "data": {"score": 73 }},
{"label": "Day 2", "data": {"score": 64 }},
{"label": "Day 3", "data": {"score": 72}}
]
} ]
<table>
<tr>
<td>
</td>
<td>
Score
</td>
<td>
Success
</td>
</tr>
<tr>
<td>
Day 3
</td>
<td>
72
</td>
<td>
72
</td>
</tr>
<tr>
<td>
Day 2
</td>
<td>
64
</td>
<td>
64
</td>
</tr>
<tr>
<td>
Day 1
</td>
<td>
73
</td>
<td>
73
</td>
</tr>
</table>
The solution i came up is:
<table >
<tr>
<td> </td>
<td>
{this.props.GraphData[0].label}
</td>
<td>
{this.props.GraphData[1].label}
</td>
</tr>
<tr>
<td> </td>
<td>
{this.props.GraphData[0].tabledata.data.map(row => ([ <tr key={i}> <td> {row.score}</td> </tr> )])};
</td>
<td>
{this.props.GraphData[1].tabledata.data.map(row => ([ <tr key={i}> <td> {row.score}</td> </tr> )])};
</td>
</tr>
</table>
How can I turn with reverse.map the values to appear in descending order (the first row (day 3) and last row (day 1).
Finally is there a way to avoid using [0] or [1] from the data file but to use mapping for all the rows and columns of the table?
first of all, your data structure is adding complexity as hell, and i advice you to structure it well so you could easily consume it, I've made a refactoring for your code and also restructured your data with a generic way so even day4, ...dayn could be shown, that shows well how complex the consumption became if we think generically, so this is what I've got, so rename this file as Table.jsx and try to import it as so import Table from './Table';:
import React from 'react';
import { get, map, reduce, uniq, find, orderBy } from 'lodash';
const data = [
{
id: '1',
label: 'Score',
tabledata: [
{ label: 'Day 1', data: { score: 73 } },
{ label: 'Day 2', data: { score: 64 } },
{ label: 'Day 3', data: { score: 72 } },
{ label: 'Day 5', data: { score: 60 } }
]
},
{
id: '2',
label: 'Success',
tabledata: [
{ label: 'Day 1', data: { score: 73 } },
{ label: 'Day 2', data: { score: 64 } },
{ label: 'Day 3', data: { score: 73 } }
]
}
];
const columnsHeaders = ['day', ...map(data, 'label')];
const days = uniq(
reduce(
data,
(acc, item) => [...acc, ...map(get(item, 'tabledata'), 'label')],
[]
)
);
const restructuredData = reduce(
days,
(acc, day) => {
const dayData = reduce(
map(data, 'label'),
(dayDataAcc, colName) => {
return {
...dayDataAcc,
day,
[colName]: get(
find(get(find(data, { label: colName }), 'tabledata'), {
label: day
}),
['data', 'score']
)
};
},
{}
);
return [...acc, dayData];
},
[]
);
const sortedData = orderBy(restructuredData, 'day', 'desc');
const TableHeaders = () => (
<thead>
<tr>{map(columnsHeaders, (col, index) => <th key={index}>{col}</th>)}</tr>
</thead>
);
// checking our data
console.log('restructuredData', restructuredData);
console.log('sortedData', sortedData);
const TableRows = ({ data }) => (
<tbody>
{map(data, ({ day, Score: score, Success: success }) => (
<tr key={day}>
<td>{day || '-'}</td>
<td>{score || '-'}</td>
<td>{success || '-'}</td>
</tr>
))}
</tbody>
);
export default () => (
<table>
<TableHeaders />
<TableRows data={sortedData} />
</table>
);

How to print data in Tabular format from this given JSON

I am trying to print the data under tabular format .
The data which is present under "properties" (ApprovalStatusShrtStrngVal and FluidCodeShrtStrngVal)
I have tried as
<div ng-app="myapp" ng-controller="FirstCtrl">
<table border="1">
<tr>
<th ng-repeat="(key, val) in collectioninfo.records.properties">{{ key }}</th>
</tr>
<tr ng-repeat="row in collectioninfo">
<td ng-repeat="column in row">
{{ column }}
</td>
</tr>
</table>
</div>
JSON is
{
"records": [{
"keys": ["n"],
"length": 1,
"_fields": [{
"identity": {
"low": 1128,
"high": 0
},
"labels": ["TestLabel"],
"properties": {
"ApprovalStatusShrtStrngVal": "Working",
"FluidCodeShrtStrngVal": "P"
}
}],
"_fieldLookup": {
"n": 0
}
}, {
"keys": ["n"],
"length": 1,
"_fields": [{
"identity": {
"low": 1129,
"high": 0
},
"labels": ["TestLabel"],
"properties": {
"ApprovalStatusShrtStrngVal": "Working",
"FluidCodeShrtStrngVal": "P"
}
}],
"_fieldLookup": {
"n": 0
}
}],
"summary": {
"statement": {
"text": "MATCH (n:TestLabel) RETURN n LIMIT 25",
"parameters": {}
},
"statementType": "r",
"counters": {
"_stats": {
"constraintsRemoved": 0
}
},
"updateStatistics": {
"_stats": {
"constraintsRemoved": 0
}
},
"plan": false,
"profile": false,
"notifications": [],
"server": {
"address": "localhost:7687",
"version": "Neo4j/3.2.0"
},
"resultConsumedAfter": {
"low": 37,
"high": 0
},
"resultAvailableAfter": {
"low": 3,
"high": 0
}
}
}
http://jsfiddle.net/9fR23/498/
please let me know how to fix this
ApprovalStatusShrtStrngVal FluidCodeShrtStrngVal (Header)
Working P (Values)
You have to loop through your array properly to get the desired result.
<table border="1">
<tr>
<th ng-repeat="(key, val) in collectioninfo.records[0]._fields[0].properties">{{ key }}</th>
</tr>
<tr ng-repeat="row in collectioninfo.records">
<td ng-repeat="column in row._fields[0].properties">
{{ column }}
</td>
</tr>
</table>
Working Fiddle :http://jsfiddle.net/9fR23/499/

Using ng-repeat on deep nest json

I'm playing around with Angular for the first time and having trouble with ng-repeat, repeating thought a json
[
{
"class": "Torture",
"type": "Cruiser",
"name": "The Impending Doom",
"leadership": 7,
"pts": "250 pts",
"speed": "35cm",
"turns": "90\u00B0",
"armour": 5,
"squadron": "Death Makes",
"hitpoints": 6,
"weapons": [
{
"name": "Impaler",
"firepower": 2,
"ordnances": [
{
"type": "Attack Craft",
"range": "30cm"
}
]
}
],
"refits": {},
"crew skills": {},
"battle log": [
{
"Data": "",
"Log": ""
}
]
},
{
"class": "Torture",
"type": "Cruiser",
"name": "Pain Giver",
"leadership": 7,
"pts": "250 pts",
"speed": "35cm",
"turns": "90\u00B0",
"armour": 5,
"squadron": "Death Makes",
"hitpoints": 6,
"weapons": [
{
"name": "Launch Bays",
"firepower": 4,
"ordnances": [
{
"type":"Fighters",
"range": "30cm"
},
{
"type":"Bombers",
"range": "20cm"
},
{
"type":"Boats",
"range": "30cm"
}
]
},
{
"name": "Prow Torpedo Tubes",
"firepower": 4,
"ordnances": [
{
"type": "Torpedos",
"range": "30cm"
}
]
}
],
"refits": {},
"crew skills": {},
"battle log": [
{
"Data": "",
"Log": ""
}
]
}
]
Now the problem I have is when I try to repeat thought the ordnance's I get the worry amount as there a two different amount of ordnance's.
Here my HTML
<div ng-repeat="ship in fleet" class="squadron__table">
<table>
<caption>{{ ship.name }}</caption>
<tr>
<td class="space">{{ ship.type }}</td>
<td class="space">{{ ship.class }}</td>
<td class="space">{{ ship.leadership }}</td>
<td class="space">{{ ship.speed }}</td>
<td class="space">{{ ship.turns }}</td>
<td class="space">{{ ship.armour }}</td>
<td class="space">{{ ship.hitpoints }}</td>
<td class="space">{{ ship.pts }}</td>
</tr>
<tr>
<th colspan="2">Armament</th>
<th colspan="2">Fire power</th>
<th colspan="4">Ordnance</th>
</tr>
<tr ng-repeat="weapon in ship.weapons">
<td colspan="2">{{ weapon.name }}</td>
<td colspan="2">{{ weapon.firepower }}</td>
<td colspan="2">
{{ weapon.ordnances.type }}
---
{{ weapon.ordnances.range }}
</td>
</tr>
</table>
</div>
and the controller
$http.get( '/json/' + $routeParams.squadrionName + '.json', { cache: $templateCache } )
.success(function( data) {
$scope.fleet = data;
})
The end result I'm looking for is
when the ship has launch bays and torpedo it print s out the three different type of ship and the one torpedos.
ordnances can have one or more than one items so you need to use the ngRepeat again, like this:
<td colspan="4">
<div ng-repeat="ordnance in weapon.ordnances">
{{ ordnance.type }} --- {{ ordnance.range }}
</div>
</td

Resources