I need to render the below object into subsequent tr/tds via JSX...
{
"0": [
{
"colIndex": 0,
"data": {
"richTextModule": "Data row 1 cell 1"
}
},
{
"colIndex": 0,
"data": {
"richTextModule": "Data row 2 cell 1"
}
}
],
"1": [
{
"colIndex": 1,
"data": {
"richTextModule": "Data row 1 cell 2"
}
},
{
"colIndex": 1,
"data": {
"richTextModule": "Data row 2 cell 2"
}
}
],
"2": [
{
"colIndex": 2,
"data": {
"richTextModule": "Data row 1 cell 3"
}
},
{
"colIndex": 2,
"data": {
"richTextModule": "Data row 2 cell 3"
}
},
{
"colIndex": 2,
"data": {
"richTextModule": "Data row 3 cell 3"
}
}
]
}
I've tried
Object.values(obj).map((column, index) => {
return column.map((row, rowIndex) => {
return obj[index][rowIndex].data.richTextModule;
});
}
Expected output should be...
<tr>
<td>Data row 1 cell 1</td>
<td>Data row 1 cell 2</td>
<td>Data row 1 cell 3</td>
</tr>
<tr>
<td>Data row 2 cell 1</td>
<td>Data row 2 cell 2</td>
<td>Data row 2 cell 3</td>
</tr>
Any ideas on how to achieve this?
Think what you're trying to do is:
<table>
{Object.values(obj).map((col, index) => <tr key={index}>{
col.map((row, rowIndex) => <td key={rowIndex}>${obj[index][rowIndex].data.richTextModule}</td>)
}</tr>
)}
</table>
or you could do:
<table>
{Object.values(obj).map((col, index) => {
return (
<tr key={index}>
{col.map((row, rowIndex) => {
return <td key={rowIndex}>${obj[index][rowIndex].data.richTextModule}</td>
})}
</tr>
)
})}
</table>
You should return in a map, reference:
Rendering an array.map() in React
You also should add a key, reference:
Lists and Keys
Related
I have the following table and want to convert it into JSON in a specific way
<table>
<thead>
<tr>
<th>Column 1</th>
<th>Column 2</th>
<th>Column 3</th>
</tr>
</thead>
<tbody>
<tr>
<td>A1</td>
<td>A2</td>
<td>A3</td>
</tr>
<tr>
<td>B1</td>
<td>B2</td>
<td>B3</td>
</tr>
<tr>
<td>C1</td>
<td>C2</td>
<td>C3</td>
</tr>
</tbody>
</table>
My expected output would be like this as I need to compare the data over UI in html table and a json file having expected data (Note: there may be a varying number of rows):
{
"myrows" : [
{
"Column 1" : "A1",
"Column 2" : "A2",
"Column 3" : "A3"
},
{
"Column 1" : "B1",
"Column 2" : "B2",
"Column 3" : "B3"
},
{
"Column 1" : "C1",
"Column 2" : "C2",
"Column 3" : "C3"
}
]
}
How can this be accomplished?
It's fairly straight forward to loop over rows then cells in the row.
Use index values from each() command to give you access to the expected value in the JSON.
const expected = { "myrows" : [
... // as in the question, abreviated here
]}
it('check the table', () => {
cy.get('table tbody tr').each(($row, rowIndex) => {
cy.wrap($row).find('td').each(($cell, cellIndex) => {
const text = $cell.text()
expect(text).to.eq(expected.myrows[rowIndex][`Column ${cellIndex}`]
})
})
})
const rows = document.querySelectorAll("tbody tr");
const result = {
myrows: []
};
rows.forEach(r => {
const rData = {}
r.querySelectorAll("td").forEach((c, i) => {
rData[`column_${i + 1}`] = c.innerHTML;
})
result.myrows.push(rData)
})
console.log(result);
<table>
<thead>
<tr>
<th>Column 1</th>
<th>Column 2</th>
<th>Column 3</th>
</tr>
</thead>
<tbody>
<tr>
<td>A1</td>
<td>A2</td>
<td>A3</td>
</tr>
<tr>
<td>B1</td>
<td>B2</td>
<td>B3</td>
</tr>
<tr>
<td>C1</td>
<td>C2</td>
<td>C3</td>
</tr>
</tbody>
</table>
following approach I have followed, taking reference from answer given by "Genevieve OR" on my post, Thanks to #Genevieve OR
var headerList = []
cy.get('table thead tr th').each(($el)=>{
var headerName = $el.text()
headerList.push(headerName)// dynamically make a list of header
)}.then(()=>{
var jsonData = [];
cy.get('table tbody').find('tr').each(($row, rowIndex) => {
jsonData[rowIndex] = {};// creates object for each row
cy.wrap($row).find('td').each(($cell, cellIndex) => {
const text = $cell.text()
jsonData[rowIndex][headerList[cellIndex]] = text
const expected = { "myrows" :jsonData}
})
})
})
My output
{
"myrows": [
{
"column_1": "A1",
"column_2": "A2",
"column_3": "A3"
},
{
"column_1": "B1",
"column_2": "B2",
"column_3": "B3"
},
{
"column_1": "C1",
"column_2": "C2",
"column_3": "C3"
}
]
}
HTML table
<thead>
<tr>
<th class="text-center">1</th>
<th class="text-center">3</th>
<th class="text-center">2</th>
</tr>
</thead>
<tbody class="result_body">
</tbody>
data
var data = [
{
"0": "1",
"1": "20"
},
{
"0": "2",
"1": "30"
},
{
"0": "3",
"1": "5"
}
]
I create one table with th name 1,3,2, after that inside jquery I try to loop the data and append into the table. But it will follow the sequence with is 1,2,3. How can I append the data follow the table sequence with is 1,3,2?
Jquery Data output
<th>
<td>20</td>
<td>30</td>
<td>5</td>
<th>
Data correct should be
<th>
<td>20</td>
<td>5</td>
<td>30</td>
<th>
code here
https://jsfiddle.net/vwL0frhm/1/
Iterate your headers, and find the corresponding value (instead to iterate the array):
$('#opt_head th').each(function(dkey, dvalue) {
let textHeader = $(dvalue).text();
let value = data.find(o => o[0] === textHeader)[1];
html += "<td>"+ value +"</td>";
});
jsfiddle: https://jsfiddle.net/hansfelix50/Ltqvr3bm/
I am out of ideas how to populate dynamically my table. This table is result of endpoint response:
{props.types[2].length > 0 ? (
<div className="onepager-bottomtables-table ">
<h1 className="onepager-bottomtables-h1">UNIQUE Types</h1>
<table className="table table-striped table-bordered table-sm table-hover">
<thead className="thead-dark">
<tr>
<th>Type</th>
<th>Plan Name</th>
<th>More</th>
<th>Statistics</th>
</tr>
</thead>
<tbody className="table-hover">
{DataExtract.uniquePensionTypes(props.types[2]).map(
(element, index) => (
<tr key={index}>
<td className="align-middle" id="types-type">
{element}
</td>
<td className="align-middle">{element}</td>
<td className="align-middle">More</td>
<td>
//***THIS IS THE PROBLEM PART OF THE CODE********
<table className="onepager-small-table">
<thead>
<tr>
<th></th>
{DataExtract.uniqueYearsPension(props.types[2]).map(
(element, index) => (
<th key={index}>{element}</th>
)
)}
</tr>
</thead>
<tbody>
{console.log(
DataExtract.participantsPension(props.types[2])
)}
<tr>
<th>Participants</th>
</tr>
<tr>
<th>Total Asset</th>
</tr>
<tr>
<th>Net Asset</th>
</tr>
</tbody>
</table>
</td>
</tr>
)
)}
</tbody>
</table>
</div>
) : (
""
)}
I am pasting all the code to get the picture. The data I get (props.types[2]) looks like this for example:
"SumPensionTypes": [
{
"Type": "DefinedBenefitPension",
"Description": null,
"Year": 2016,
"Participants": 9.0,
"TotalAssets": 6668305.0,
"NetAssets": 6668305.0,
"PlanName": null
},
{
"Type": "DefinedContributionPension",
"Description": null,
"Year": 2016,
"Participants": 72.0,
"TotalAssets": 17230395.0,
"NetAssets": 17230395.0,
"PlanName": null
},
{
"Type": "DefinedBenefitPension",
"Description": null,
"Year": 2017,
"Participants": 7.0,
"TotalAssets": 2096999.0,
"NetAssets": 2096999.0,
"PlanName": null
},
{
"Type": "DefinedContributionPension",
"Description": null,
"Year": 2017,
"Participants": 56.0,
"TotalAssets": 16114639.0,
"NetAssets": 16114639.0,
"PlanName": null
},
{
"Type": "DefinedBenefitPension",
"Description": null,
"Year": 2018,
"Participants": 0.0,
"TotalAssets": 0.0,
"NetAssets": 0.0,
"PlanName": null
},
{
"Type": "DefinedContributionPension",
"Description": null,
"Year": 2018,
"Participants": 49.0,
"TotalAssets": 21954205.0,
"NetAssets": 21954205.0,
"PlanName": null
}
]
So currently all looks like this picture:
Now it comes the hard part (for me). I am trying to fill the small tables with the summed data for the objects with same type. As you can see from data there are 2 types - DefinedBenefitPension and DefinedContributionPension which repeats for 2016,2017,2018. I combined them with this method and populate them in first column:
//***************DIFFERENT PENSION TYPES********************* */
const uniquePensionTypes = data => {
const unique = [...new Set(data.map(plan => plan.Type))];
return unique;
};
The problem is that I want to populate small table as per plan type. If you see the picture and data you will understand how it is suppose to be populated as they have same types but statistics are year-for-year.
Here's some sample code to help.
getDataRow is a helper function that takes 3 arguments:
Your data (props.types[2])
The pension type ("DefinedBenefitPension" or "DefinedContributionPension")
The metric (like "Participants")
You can use the resulting object to map to table cells according to year.
https://repl.it/repls/UprightAdmiredBlogclient
// DataExtract.uniqueYearsPension(props.types[2])
const years = [2016, 2017, 2018]
function getDataRow(data, type, key) {
const rowData = {}
data.filter(pension => pension.Type == type).forEach(pension => {
rowData[pension.Year] = pension.Participants
})
return rowData
}
// { '2016': 9, '2017': 7, '2018': 0 }
const participants = getDataRow(data, 'DefinedBenefitPension', 'Participants')
// <td key=2016>9</td>
// <td key=2017>7</td>
// <td key=2018>0</td>
const row = years.map(year => {
return <td key={year}>
{participants[year]}
</td>
})
I want to iterate table with one property but to have 4 td in one row, and to continue like that till the end...
I want like this:
<table>
<tr>
<td>
<mat-checkbox>1</mat-checkbox>
</td>
<td>
<mat-checkbox>2</mat-checkbox>
</td>
<td>
<mat-checkbox>3</mat-checkbox>
</td>
<td>
<mat-checkbox>4</mat-checkbox>
</td>
</tr>
<tr>
<td>
<mat-checkbox>5</mat-checkbox>
</td>
<td>
<mat-checkbox>6</mat-checkbox>
</td>
<td>
<mat-checkbox>7</mat-checkbox>
</td>
</tr>
</table>
I tried like this, but it's al in one column :
lista = [
{ value: "1" },
{ value: "2" },
{ value: "3" },
{ value: "4" },
{ value: "5" },
{ value: "6" },
{ value: "7" },
<table *ngFor="let list of lista">
<tr>
<td>
<mat-checkbox>{{ list.value }}</mat-checkbox>
</td>
</tr>
</table>
You need to group your array firstly in groups of 4 (chunk size), then iterate over it simply in your template.
In your component:
const lista = [
{ value: "1" },
{ value: "2" },
{ value: "3" },
{ value: "4" },
{ value: "5" },
{ value: "6" },
{ value: "7" }
];
const chunkSize = 4;
// Group in chunks of 4 and take only truthy values
const groups = lista
.map((x, index) => {
return index % chunkSize === 0 ? lista.slice(index, index + chunkSize): null;
})
.filter(x => x);
In your template:
<table >
<tr *ngFor="let item of groups">
<td *ngFor = "let innerItem of item">
<mat-checkbox>{{ innerItem.value }}</mat-checkbox>
</td>
</tr>
</table>
you can use 2d array for your table like below:
lista = [
[
{value: '1'},
{value: '2'},
{value: '3'},
{value: '4'}
],
[
{value: '5'},
{value: '6'},
{value: '7'},
{value: '8'}
]
];
and for HTML
<table >
<tr *ngFor="let row of lista">
<td *ngFor="let col of row">
<mat-checkbox>{{ col.value }}</mat-checkbox>
</td>
</tr>
</table>
I had an requirement like this Use of rowspan to group hierarchical data but expanding step by step onclick event using any javascript framework with ajax. So far have googled this
http://www.igniteui.com/tree-grid/angular
Any help with example or any approach.
Hoping it would help someone, here is the jsfiddle [http://jsfiddle.net/djlerman/bbj8k9pe/][1]
Adding code- if jsfiddle is dead. Also note, echo ajax not working in stackoverflow run snippet. Paste this code in jsfiddle.
/* This is an echo of some data sent back via ajax */
/* This data should be filtered by nodeID and return only childNodeID's. */
/* vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv. */
var jsonData = {
"nodeID": {
"1": [
{"ID": "1.1",
"childNodeType": "branch",
"childData": [
"1.1: column 1",
"1.1: column 2"
]
},
{"ID": "1.2",
"childNodeType": "leaf",
"childData": [
"1.2: column 1",
"1.2: column 2"
]
},
{"ID":"1.3",
"childNodeType": "leaf",
"childData": [
"1.3: column 1",
"1.3: column 2"
]
}
],
"1.1": [
{"ID":"1.1.1",
"childNodeType": "leaf",
"childData": [
"1.1.1: column 1",
"1.1.1: column 2"
]
},
{"ID":"1.1.2",
"childNodeType": "leaf",
"childData": [
"1.1.2: column 1",
"1.1.2: column 2"
]
}
],
"2": [
{"ID":"2.1",
"childNodeType": "leaf",
"childData": [
"2.1: column 1",
"2.1: column 2"
]
},
{"ID":"2.2",
"childNodeType": "leaf",
"childData": [
"2.2: column 1",
"2.2: column 2"
]
},
{"ID":"2.3",
"childNodeType": "leaf",
"childData": [
"2.3: column 1",
"2.3: column 2"
]
}
],
"3": [
{"ID":"3.1",
"childNodeType": "leaf",
"childData": [
"3.1: column 1",
"3.1: column 2"
]
},
{"ID":"3.2",
"childNodeType": "leaf",
"childData": [
"3.2: column 1",
"3.2: column 2"
]
},
{"ID":"3.3",
"childNodeType": "leaf",
"childData": [
"3.3: column 1",
"3.3: column 2"
]
}
]
}
};
/* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
/* This is an echo of some data sent back via ajax */
/* This data should be filtered by nodeID and return only childNodeID's. */
// initialize treeTable
$("#example-basic").treetable({
expandable: true,
onNodeExpand: nodeExpand,
onNodeCollapse: nodeCollapse
});
// expand node with ID "1" by default
$("#example-basic").treetable("reveal", '1');
// Highlight a row when selected
$("#example-basic tbody").on("mousedown", "tr", function() {
$(".selected").not(this).removeClass("selected");
$(this).toggleClass("selected");
});
function nodeExpand () {
// alert("Expanded: " + this.id);
getNodeViaAjax(this.id);
}
function nodeCollapse () {
// alert("Collapsed: " + this.id);
}
function getNodeViaAjax(parentNodeID) {
$("#loadingImage").show();
// ajax should be modified to only get childNode data from selected nodeID
// was created this way to work in jsFiddle
$.ajax({
type: 'POST',
url: '/echo/json/',
data: {
json: JSON.stringify( jsonData )
},
success: function(data) {
$("#loadingImage").hide();
var childNodes = data.nodeID[parentNodeID];
if(childNodes) {
var parentNode = $("#example-basic").treetable("node", parentNodeID);
for (var i = 0; i < childNodes.length; i++) {
var node = childNodes[i];
var nodeToAdd = $("#example-basic").treetable("node",node['ID']);
// check if node already exists. If not add row to parent node
if(!nodeToAdd) {
// create row to add
var row ='<tr data-tt-id="' +
node['ID'] +
'" data-tt-parent-id="' +
parentNodeID + '" ';
if(node['childNodeType'] == 'branch') {
row += ' data-tt-branch="true" ';
}
row += ' >';
// Add columns to row
for (var index in node['childData']) {
var data = node['childData'][index];
row += "<td>" + data + "</td>";
}
// End row
row +="</tr>";
$("#example-basic").treetable("loadBranch", parentNode, row);
}
}
}
},
error:function(error){
$("#loadingImage").hide();
alert('there was an error');
},
dataType: 'json'
});
}
#loadingImage {
position:absolute;
width:48px; /*image width */
height:48px; /*image height */
left:50%;
top:75px;
margin-left:-24px; /*image width/2 */
margin-top:-24px; /*image height/2 */
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<link href="http://ludo.cubicphuse.nl/jquery-treetable/css/jquery.treetable.theme.default.css" rel="stylesheet"/>
<link href="http://ludo.cubicphuse.nl/jquery-treetable/css/jquery.treetable.css" rel="stylesheet"/>
<script src="http://ludo.cubicphuse.nl/jquery-treetable/jquery.treetable.js"></script>
<div id="loadingImage" style="display: none">
<img src="//i.stack.imgur.com/FhHRx.gif" />
</div>
<table id="example-basic" >
<caption>
Expand all
Collapse all
</caption>
<thead>
<tr>
<th>Tree column</th>
<th>Additional data</th>
</tr>
</thead>
<tbody>
<tr data-tt-id="1" data-tt-branch='true'>
<td>1: column 1</td>
<td>1: column 2</td>
</tr>
<tr data-tt-id="2" data-tt-branch='true'>
<td>2: column 1</td>
<td>2: column 2</td>
</tr>
<tr data-tt-id="3" data-tt-branch='true'>
<td>3: column 1</td>
<td>3: column 2</td>
</tr>
</tbody>
</table>