Array of objects to table rows and columns - javascript

is there any javascript library available to convert the nested array of object to table rows and columns...
sample data..
[
{
"headerName": "Product"
},
{
"headerName": "Sale Rate",
"children": [
{
"headerName": "Sales",
"children": [
{
"headerName": "Last Year Sale"
},
{
"headerName": "This Year Sale"
}
]
},
{
"headerName": "Profits",
"children": [
{
"headerName": "Last Year Profit"
},
{
"headerName": "This Year Profit"
}
]
}
]
}
]
need to build the below table structure(row, column along with row and col span) from the data
<table>
<tr>
<th rowspan="3">Product</th>
<th colspan="4">Sale Rate</th>
</tr>
<tr>
<th colspan="2">Sales</th>
<th colspan="2">Profits</th>
</tr>
<tr>
<th>Last Year Sale</th>
<th>This Year Sale </th>
<th>Last Year Profit</th>
<th>This Year Profit</th>
</tr>
</table>
what i tried so far
https://codesandbox.io/s/modest-booth-inhzvm
struggling to get the column and row span from data

I don't know if there is a library that does this.
I looked at your example code and you might be able to use it with slight modifications.
When you are parsing your data check if you have sub level data and if so then create a nested table. Call your original function on the nested data.
Here is an example you will have to adapt it to your use case:
function walkDownTree(data, callback, value = null) {
callback(data, value);
if (data.children.length) {
var items = data.children;
for (var i=0;i<items.length;i++) {
let item = items[i];
walkDownTree(item, callback, value);
}
}
}
function logItems(item) {
console.log(item.nodeName)
}
var results = walkDownTree(data, logItems);
The third parameter is an optional parameter sometimes used to keep track of state data.
walkDownTree(document.body, logItems, count++);

Related

how to give fixed table rows using typescript

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>

Rearrage html table column in jquery

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/

fill table dynamically using GET request

an empty table. To fill the product table, its content should be created dynamically by using JavaScript to insert the data into the table. The data should be requested from the webserver. You should first send an AJAX GET request to the Web service. When this request returns successfully, you should insert the returned JSON data into your table using the DOM
You can try datatable plugin to fullfill your scenario
to work with this your data should be in the format of
{ "draw": 1, "recordsTotal": 57, "recordsFiltered": 57, "data": [
[
"Airi",
"Satou",
"Accountant",
"Tokyo",
"28th Nov 08",
"$162,700"
],
[
"Angelica",
"Ramos",
"Chief Executive Officer (CEO)",
"London",
"9th Oct 09",
"$1,200,000"
],
]
}
HTML CODE
<table id="example" class="display" style="width:100%">
<thead>
<tr>
<th>First name</th>
<th>Last name</th>
<th>Position</th>
<th>Office</th>
<th>Start date</th>
<th>Salary</th>
</tr>
</thead>
<table>
JS CODE:
$(document).ready(function() {
$('#example').DataTable( {
"ajax": "../server_side/scripts/server_processing.php"
} );
} );
include below scripts too
https://code.jquery.com/jquery-3.3.1.js
https://cdn.datatables.net/1.10.20/js/jquery.dataTables.min.js
You can append the dynamically created html using innserHTML property ofDOM element.
Example
fetch('<some URL>')
.then((response) => {
let data = response.json(); // Let supposed the data is in this format [{ id: 1 }, { id: 2 }, { id: 3 }]
let tr = '';
data.forEach(function(value) {
tr += `<tr><td>${data.id}</td></tr>`;
});
document.querySelector('#table_id tbody').innerHTML = tr; //Append the data
}).catch(error => {
console.log(error);
});
Or use document.createElement to create the element and then append it to the DOM
fetch('<some URL>')
.then((response) => {
let data = response.json(); // Let supposed the data is in this format [{ id: 1 }, { id: 2 }, { id: 3 }]
let tr = '';
let tableBody = document.querySelector('#table_id');
data.forEach(function(value) {
let tr = document.createElement('tr');
tr.textContent = data.id
tableBody.appendChild(tr);
});
}).catch(error => {
console.log(error);
});
HTML
<table id="table_id">
<tbody>
</tbody>
</table>

Jquery displaying items in nested loop

I would like to display items belonging to different customers. To this effect, i am fetching data through an ajax call and therefater grouping the data based on each unique customer. I then append the grouped data to my html.
Structure of my grouped data looks like:
"John Doe": [
{
"Item_id" : 1
"Item_name": "abc"
},
{
"Item_id" : 2
"Item_name": "def"
},
],
"Jane Doe":
{
"Item_id" : 3
"Item_name": "ghi"
},
{
"Item_id" : 4
"Item_name": "jkl"
},
]
My code looks like:
$.each(groupedData, function (key, value) {
$('.cust_items').append(`
<h4 class="mb-0"> ` + key + `</h4>
<table id="dataTable">
<thead>
<th>Item No.</th>
<th>Item Name</th>
</thead>
<tbody></tbody>
</table>
`);
$.each(value, function (ky, val) {
$('#dataTable tbody').append(
`<tr>
<td>
` + ky + `
</td>
<td>
` + val.Item_name + `
</td>
</tr>
`);
});
});
I am facing an inssue whereby all items are being displayed under the first customer while the data is being displayed correctly under the second customer.
You're missing commas after the properties and Jane Doe property's objects aren't enclosed in []. Consider changing your groupedData object as the syntax isn't right.
Edit: Also adjusted the template string and accessing the table with dynamic id as well.
Sample:
let groupedData = {
"John Doe": [{
"Item_id": 1,
"Item_name": "abc"
},
{
"Item_id": 2,
"Item_name": "def"
}
],
"Jane Doe": [{
"Item_id": 3,
"Item_name": "ghi"
},
{
"Item_id": 4,
"Item_name": "jkl"
}
]
};
$.each(groupedData, function(key, value) {
$('.cust_items').append(`
<h4 class="mb-0">${key}</h4>
<table id="dataTable_${key.split(' ').join('_')}">
<thead>
<th>Item No.</th>
<th>Item Name</th>
</thead>
<tbody></tbody>
</table>
`);
$.each(value, function(ky, val) {
$(`#dataTable_${key.split(' ').join('_')} tbody`).append(
`<tr>
<td>
${ky}
</td>
<td>
${val.Item_name}
</td>
</tr>
`);
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="cust_items">
</div>
I'm a bit late to the party, but here's a fun and practical way to display your data dynamically using the <template> element and vanilla JS.
The in-code comments should make clear how it works.
Note: Be wary of adding the id attribute to elements inside a template (or inside a loop for that matter) cuz duplicate id values are bad.
const data = {
"John Doe" :
[
{ "Item_id" : 1, "Item_name": "abc" },
{ "Item_id" : 2, "Item_name": "def" }
],
"Jane Doe" : [
{ "Item_id" : 3, "Item_name": "ghi" },
{ "Item_id" : 4, "Item_name": "jkl" }
]
};
// Identifies HTML elements and an array of the names
const
container = document.getElementsByClassName("cust_items")[0],
template = document.getElementById("group_template"),
names = Object.keys(data);
// Loops through the names and adds a new copy of the template's contents for each one
for (let name of names){
// Identifies HTML elements (Technically, some are `document fragments`)
const
copyOfTemplate = document.importNode(template.content, true),
header = copyOfTemplate.querySelector(".header"),
tbody = copyOfTemplate.querySelector("tbody");
// Sets the header for the new copy of the template's contents
header.innerHTML = name;
// Loops through the items for this name and makes a new row for each one
for(let item of data[name]){
// Identifies strings and new HTML elements
const
itemId = item["Item_id"],
itemName = item["Item_name"],
row = document.createElement("TR"),
idCell = document.createElement("TD"),
nameCell = document.createElement("TD");
// Sets the item number and item name in their respective cells
idCell.innerHTML = itemId;
nameCell.innerHTML = itemName;
// Adds the cells to the new row
row.appendChild(idCell);
row.appendChild(nameCell);
// Adds the new row to the `tbody` within the new copy of the template's contents
tbody.appendChild(row);
}
// The new copy is ready to go live -- adds it to the page
container.appendChild(copyOfTemplate);
}
.header{ font-size: 1.2em; margin-bottom: 0.3em; }
table{ margin-left: 0.3em; margin-top: 0; border-collapse: collapse; }
th, td{ padding: 0.3em 0.5em; }
<div class="cust_items"></div>
<template id="group_template">
<h4 class="header"></h4>
<table>
<thead>
<th>Item No.</th>
<th>Item Name</th>
</thead>
<tbody></tbody>
</table>
<hr />
</template>

Knockout table bindings with an object

I have a javascript object that I want to bind to a table using KnockoutJS
Here's my object:
var data = {
"Warnings": {
"numbers": 30,
"content": [
{
"number" : 3001,
"description" : "There may be a problem with the device you are using if you use the default profile"
},
{
"number" : 3002,
"description" : "There may be a problem with the device you are using if you don't use the default profile"
}
]
},
"Errors": {
"numbers": 20,
"content": [
{
"number": 1000,
"description": "No network is loaded"
},
{
"number": 1000,
"description": "No network is loaded"
}
]
}
};
ko.applyBindings(data);
Here's my html code:
<table class="table table-hover">
<thead>
<tr>
<th style="width:100px">Numero</th>
<th>Description</th>
</tr>
</thead>
<tbody data-bind="foreach: Warnings.content">
<tr data-bind="foreach: $data">
<td data-bind="text: $data.number"></td>
<td data-bind="text: $data.description"></td>
</tr>
</tbody>
</table>
Here's a JSFiddle: http://jsfiddle.net/etiennenoel/KmKEB/
I really need to use this format for my data Object.
I don't know why I'm not having the Warnings listed in a table since I'm not getting any errors...
You have an extra foreach that is not needed. Simply remove the foreach on your tr. The foreach on your tbody will assign a new value for $data for each tr that is rendered in the loop.

Categories