I have the following code that returns the values for the tbody of the table.
In this table I want to have tfoot to add the value of the last column and I'm doing it this way:
var data = [
{Id: "1", Quantidade: "14", Preco: "3.10", },
{Id: "2", Quantidade: "5", Preco: "1.80", },
{Id: "3", Quantidade: "3", Preco: "0.45", },
{Id: "4", Quantidade: "4", Preco: "9.83", },
{Id: "5", Quantidade: "2", Preco: "15.30", },
{Id: "6", Quantidade: "3", Preco: "9.98", },
];
$('.enc-per').on("click", function() {
var linha = ``;
Object.keys(data).forEach(b => {
Id = data[b].Id;
Qtd = data[b].Quantidade;
Preco = data[b].Preco;
Total = data[b].Quantidade * data[b].Preco;
linha += `<tr>
<td class="text-center text-muted"> ${Id}</td>
<td class="text-center text-muted"> ${Qtd}</td>
<td class="text-center text-muted"> ${Preco}</td>
<td class="text-center text-muted"> ${Total}</td>
</tr>`;
})
$("#encofinal tbody").html(linha);
$('.encofinal').DataTable({
fixedHeader: {
header: true,
footer: true
},
footerCallback: function(){
const sumProduct = this
.api()
.rows({search:'applied'})
.data()
.toArray()
.reduce((res,row) => {
const Quantidade = row[1];
const Preco = row[2];
return res += Quantidade*Preco}, 0).toFixed(2);
$('#sumproduct').text(sumProduct);
}
});
});
<link href="https://cdn.datatables.net/1.11.4/css/dataTables.bootstrap5.min.css" rel="stylesheet">
<link href="https://cdn.datatables.net/buttons/2.2.2/css/buttons.bootstrap5.min.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.datatables.net/1.11.4/js/jquery.dataTables.min.js"></script>
<script src="https://cdn.datatables.net/1.11.4/js/dataTables.bootstrap5.min.js"></script>
<script src="https://cdn.datatables.net/buttons/2.2.2/js/dataTables.buttons.min.js"></script>
<script src="https://cdn.datatables.net/buttons/2.2.2/js/buttons.bootstrap5.min.js"></script>
<button type="button" class="btn btn-info enc-per" style="float: right; margin-right: 5%; margin-top: 4%;"><i class="metismenu-icon pe-7s-search"></i> Consultar </button>
<table class="align-middle mb-0 table table-border table-striped table-hover encofinal" id="encofinal">
<thead>
<tr>
<th class="text-center">Pedido</th>
<th class="text-center">Qtd</th>
<th class="text-center">Preço</th>
<th class="text-center">Valor</th>
</tr>
</thead>
<tbody>
</tbody>
<tfoot>
<tr>
<td COLSPAN="2"></td>
<td COLSPAN="3">Valor Total: <span id="sumproduct"></span>€</td>
</tr>
</tfoot>
</table>
But it returns the values correctly, but the sum of tfoot returns error.
I think the problem is sending the data to tfoot.
Can you help me solve the problem?
error console:
Uncaught TypeError: Cannot set properties of undefined (setting 'nTf')
at Fb (jquery.dataTables.min.js:40:282)
at Ba (jquery.dataTables.min.js:62:151)
at f (jquery.dataTables.min.js:108:98)
at HTMLTableElement.<anonymous> (jquery.dataTables.min.js:108:184)
at Function.each (jquery-3.6.0.min.js:2:3003)
at S.fn.init.each (jquery-3.6.0.min.js:2:1481)
at S.fn.init.u [as dataTable] (jquery.dataTables.min.js:98:199)
at HTMLButtonElement.<anonymous> (jsdashboard.js:21510:21)
at HTMLButtonElement.dispatch (jquery-3.6.0.min.js:2:43064)
at v.handle (jquery-3.6.0.min.js:2:41048)
The error is being caused by the fact that your table has an inconsistent number of columns in each row. Most have 4 but your table footer spans 5 columns (2+3):
<tr>
<td COLSPAN="2"></td>
<td COLSPAN="3">Valor Total: <span id="sumproduct"></span>€</td>
</tr>
Corrected to span only 4 columns and it works:
var data = [
{Id: "1", Quantidade: "14", Preco: "3.10", },
{Id: "2", Quantidade: "5", Preco: "1.80", },
{Id: "3", Quantidade: "3", Preco: "0.45", },
{Id: "4", Quantidade: "4", Preco: "9.83", },
{Id: "5", Quantidade: "2", Preco: "15.30", },
{Id: "6", Quantidade: "3", Preco: "9.98", },
];
$('.enc-per').on("click", function() {
var linha = ``;
Object.keys(data).forEach(b => {
Id = data[b].Id;
Qtd = data[b].Quantidade;
Preco = data[b].Preco;
Total = data[b].Quantidade * data[b].Preco;
linha += `<tr>
<td class="text-center text-muted"> ${Id}</td>
<td class="text-center text-muted"> ${Qtd}</td>
<td class="text-center text-muted"> ${Preco}</td>
<td class="text-center text-muted"> ${Total}</td>
</tr>`;
})
$("#encofinal tbody").html(linha);
$('.encofinal').DataTable({
fixedHeader: {
header: true,
footer: true
},
footerCallback: function() {
const sumProduct = this
.api()
.rows({
search: 'applied'
})
.data()
.toArray()
.reduce((res, row) => {
const Quantidade = row[1];
const Preco = row[2];
return res += Quantidade * Preco
}, 0).toFixed(2);
$('#sumproduct').text(sumProduct);
}
});
});
<link href="https://cdn.datatables.net/1.11.4/css/dataTables.bootstrap5.min.css" rel="stylesheet">
<link href="https://cdn.datatables.net/buttons/2.2.2/css/buttons.bootstrap5.min.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.datatables.net/1.11.4/js/jquery.dataTables.min.js"></script>
<script src="https://cdn.datatables.net/1.11.4/js/dataTables.bootstrap5.min.js"></script>
<script src="https://cdn.datatables.net/buttons/2.2.2/js/dataTables.buttons.min.js"></script>
<script src="https://cdn.datatables.net/buttons/2.2.2/js/buttons.bootstrap5.min.js"></script>
<button type="button" class="btn btn-info enc-per" style="float: right; margin-right: 5%; margin-top: 4%;"><i class="metismenu-icon pe-7s-search"></i> Consultar </button>
<table class="align-middle mb-0 table table-border table-striped table-hover encofinal" id="encofinal">
<thead>
<tr>
<th class="text-center">Pedido</th>
<th class="text-center">Qtd</th>
<th class="text-center">Preço</th>
<th class="text-center">Valor</th>
</tr>
</thead>
<tbody>
</tbody>
<tfoot>
<tr>
<td COLSPAN="2"></td>
<td COLSPAN="2">Valor Total: <span id="sumproduct"></span>€</td>
</tr>
</tfoot>
</table>
Related
I need to generate following Json Object daynamically from inputs
{
"name":"USA",
"parents": [
{
"state":"California",
"id":"12",
"child":[
{
"city":"Los Angeles",
"id":"1"
},
{
"city":"San Francisco",
"id":"2"
}
]
},
{
"state":"Texas",
"id":"33",
"child":[
{
"city":"Dallas",
"id":"3"
},
{
"city":"Houston",
"id":"4"
}
]
}
]
}
from this Table of inputs
<table id="tTypeTable" class="table table-bordered" hidden="hidden" >
<tr>
<th><a class="btn btn-primary" onclick="add_tTypeParentField();"></th>
</tr>
<!-- ko foreach: {data: tTypeParentFields, as: 'tParentField'} -->
<tr>
<td>
<table class="table table-hover" >
<tr>
<th> State </th>
<th> </th>
</tr>
<tr title="tParentRow" >
<td>
<input id="state" data-bind="value: tParentField[0]"
onblur="createJSON()"/>
</td>
<td>
<input id="value" data-bind="value: tParentField[0]"
onblur="createJSON()"/>
</td>
</tr>
</table>
<table id="tChild" class="table table-hover" >
<tr>
<th> City </th>
<th> </th>
<th> <a id="childAdd" onclick="addChild(this);"></th>
</tr>
<tbody>
<tr title="tChildRow" id="tChildRow">
<td>
<input id="cityName" onblur="createJSON()"/>
</td>
<td>
<input id="cityValue" " onblur="createJSON()"/>
</td>
<td>
<a id="removeChild" onclick="deleteChild(this)" ></a>
</td>
</tr>
</tbody>
</table>
<td> <a data-bind="click: removeTTypeParentField" ></a></td>
</td>
</tr>
<!-- /ko -->
</table>
<div class="col-md-11 ">
<textarea class="form-control" id="requestData" ></textarea>
</div>
there is no problem with adding new row of inputs. I have used Knockouts for addding Parent table and used jQuery for adding child table. it's working well.
The problem is that generating Json child Object (cities).
I have tried to get value of inputs and generate Json Object in textare like this
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script th:inline="javascript">
function createJSON() {
var jsonObj = [];
$(document).ready(function() {
var valueTypeTChild = [];
var valueTypeTParent = [];
$("tr[id=tParentRow]").each(function() {
$(this).find('tr[id=tChildRow]').each(function () {
child = {
city: $(this).find('#cityName').val(),
id: $(this).find('#cityValue').val()
};
valueTypeTChild.push(child);
});
parent = {
city:$(this).find('#state').val(),
id:$(this).find('#value').val(),
child: valueTypeTChild
};
valueTypeTParent.push(parent);
);
inputItem = {
"name":"Country",
parents: valueTypeTParent
};
jsonObj.push(inputItem);
});
$('#requestData').val(JSON.stringify(jsonObj));
console.log(JSON.stringify(jsonObj));
</script>
But I'm getting this
{
"name": "USA",
"parents": [
{
"state": "California",
"id": "12",
"child": [
{
"city": "Los Angeles",
"id": "1"
},
{
"city": "San Francisco",
"id": "2"
},
{
"city": "Dallas",
"id": "3"
},
{
"city": "Houston",
"id": "4"
}
]
},
{
"state": "Texas",
"id": "33",
"child": [
{
"city": "Los Angeles",
"id": "1"
},
{
"city": "San Francisco",
"id": "2"
},
{
"city": "Dallas",
"id": "3"
},
{
"city": "Houston",
"id": "4"
}
]
}
]
}
You are giving every state the same city array without clearing it.
Move var valueTypeTChild = []; inside the $("tr[id=tParentRow]").each(function() { loop.
I have a Knockout model that have created in the snippet below.
What I'm trying to do is create a many to many relationship in a popup dialog from option rows that ive added to a option(I'm hoping this make sense when you look at the jsfiddler). When you click on the lookup link on the children column on the rows I list ALL the option rows in a dialog and with a check box list and allow the user to select the children relations to the to a specific row, hence a many to many relationship between rows.
I have defaulted the data of of my desired as a output in the first option group but I am not sure how to make this work.
I'm not sure if I'm going about this correct way and am hoping some Knockout guru can point me in the right direction to get this functionality in the popup.
/*Select Options*/
var initialData = [{
title: "User Band",
productoptionrows: [{
id: "1",
title: "25-100",
related: [{
id: "4",
title: '1 Year'
}, {
id: "5",
title: '2 Year'
}, {
id: "6",
title: '3 Year'
}]
}, {
id: "2",
title: "101-250",
related: [{
id: "7",
title: '1 Year'
}, {
id: "8",
title: '2 Year'
}, {
id: "9",
title: 'qwe'
}]
}, {
id: "3",
title: "251-500",
related: [{
id: "10",
title: '1 Year'
}, {
id: "11",
title: '2 Year'
}, {
id: "12",
title: '3 Year'
}]
}]
}, {
title: "Please select the number of years license",
productoptionrows: [{
id: "4",
title: "1 Year",
related: []
}, {
id: "5",
title: "2 Year",
related: []
}, {
id: "6",
title: "3 Year",
related: []
}, {
id: "7",
title: "1 Year",
related: []
}, {
id: "8",
title: "2 Year",
related: []
}, {
id: "9",
title: "3 Year",
related: []
}, {
id: "10",
title: "1 Year",
related: []
}, {
id: "11",
title: "2 Year",
related: []
}, {
id: "12",
title: "3 Year",
related: []
}]
}];
$(document).ready(function () {
/*Models*/
var mappingOptions = {
'productoptionrows': {
create: function (options) {
return new productoptionrow(options.data);
}
}
};
var mappingOptionsPR = {
create: function (options) {
return new productoptionrow(options.data);
}
};
var productoptionrow = function (por) {
var self = ko.mapping.fromJS(por, {}, this);
self.relatedcsv = ko.computed(function () {
return $(por.related).map(function () {
return this.id;
}).get().join(',');
}, self);
self.selectedrelated = ko.observableArray($(por.related).map(function () {
return this.id;
}).get());
};
var ProductOptionModel = function (data) {
var self = this;
self.productoptions = ko.mapping.fromJS(data, mappingOptions);
self.isOpen = ko.observable(false);
self.selectedrelated = ko.observableArray([]);
/*Control Events*/
self.addProductOption = function () {
var newoption = ko.mapping.fromJS({
title: "Please select the number of years license",
productoptionrows: ko.observableArray([{
id: "15",
title: "25-100",
related: []
}, {
id: "16",
title: "101-250",
related: []
}, {
id: "17",
title: "251-500",
related: []
}])
}, mappingOptions);
self.productoptions.push(newoption);
};
self.copyProductOption = function (productoption) {
var copy = ko.mapping.fromJS(ko.mapping.toJS(productoption), mappingOptions);
self.productoptions.push(copy);
};
self.removeProductOption = function (productoption) {
self.productoptions.remove(productoption);
};
self.addProductOptionRow = function (productoption) {
var newrow = ko.mapping.fromJS({
id: "15",
title: "25-100",
related: []
}, mappingOptionsPR);
productoption.productoptionrows.push(newrow);
};
self.removeProductOptionRow = function (productoption) {
$.each(self.productoptions(), function () {
this.productoptionrows.remove(productoption)
})
};
self.open = function (productoption, event) {
self.selectedrelated(productoption.related);
self.isOpen(true);
};
self.close = function () {
self.isOpen(false);
}
self.associaterelated = function (record, elem) {
//console.log(ko.mapping.toJS(record));
}
};
ko.applyBindings(new ProductOptionModel(initialData), document.getElementById('page-wrapper'));
});
<link href="https://code.jquery.com/ui/1.12.1/themes/ui-lightness/jquery-ui.css" rel="stylesheet" />
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.min.js"></script>
<script src="https://cdn.rawgit.com/gvas/knockout-jqueryui/075b303a/dist/knockout-jqueryui.min.js"></script>
<div id="page-wrapper">
<div>
<button title="Add Option" type="button" data-bind='click: $root.addProductOption'>Add Option</button>
</div>
<div id="options" data-bind="foreach: productoptions">
<div style="padding:10px;margin:20px;background-color:whitesmoke">
<table class="option-header" cellpadding="0" cellspacing="0">
<thead>
<tr>
<th>Group Title <span class="required">*</span></th>
<th>
<button title="Copy" type="button" class="" style="" data-bind='click: $root.copyProductOption'>Copy</button>
<button title="Delete Option" type="button" data-bind='click: $root.removeProductOption'>Delete Option</button>
</th>
</tr>
</thead>
<tbody>
<tr style="height:36px;">
<td>
<input type="text" data-bind='value: title'>
</td>
<td>
</td>
</tr>
</tbody>
</table>
<div>
<table class="option-header-rows" cellpadding="0" cellspacing="0">
<thead>
<tr class="headings">
<th>Id</th>
<th colspan="2" class="type-title">Title <span class="required">*</span></th>
<th>Children</th>
<th></th>
</tr>
</thead>
<tbody data-bind="foreach: productoptionrows">
<tr>
<td align="center">
<input required type="text" style="width:40px" data-bind='value: id'>
</td>
<td colspan="2">
<input type="text" value="25-100" data-bind='value: title'>
</td>
<td>
<input type="text" data-bind='value: relatedcsv' name="isdefault">Lookup</td>
<td>
<button title="Delete Row" type="button" data-bind='click: $root.removeProductOptionRow'>Delete Row</button>
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td align="right">
<button title="Add New Row" type="button" data-bind='click: $root.addProductOptionRow'>Add New Row</button>
</td>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
<!-- popup -->
<div data-bind="dialog: { isOpen: isOpen,title:'Select relations', modal:true }">
<div data-bind="foreach: $root.productoptions">
<div data-bind='text: title'></div>
<div data-bind="foreach: productoptionrows">
<div>
<input type="checkbox" data-bind="value: id, checked: $root.selectedrelated" style="width:auto" />
ID <span data-bind='text: id'></span> - <span data-bind='text: title'></span>
</div>
</div>
</div>
</div>
<pre data-bind="text: ko.toJSON($data, null, 2)"></pre>
</div>
I've tried to distill the many-to-many issue down to a simple example. Here, persons and things are mapped to each other. To track the mapping, each person has a list of things. For each possible thing, there is a checkbox with that value. Its checked binding is bound to the thingList for the current person.
Binding to an array makes the checkbox insert or remove its value to/from the array.
function person(name) {
return {
name,
thingList: ko.observableArray()
};
}
const vm = {
people: ko.observableArray(['Abby', 'Bill', 'Charlie'].map((n) => person(n))),
things: ko.observableArray(['apple', 'bullet', 'cup', 'doll', 'egg'])
};
ko.applyBindings(vm);
.checklist {
display: inline-block;
}
.no-bullets {
list-style-type: none;
}
.no-bullets li {
display: inline;
padding-right: 15px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<div data-bind="foreach:people">
<div>Name: <span data-bind="text:name"></span>
<div class="checklist" data-bind="foreach:$parent.things">
<label><input type="checkbox" data-bind="value:$data, checked:$parent.thingList"><span data-bind="text:$data"></span></label>
</div>
<ul class="no-bullets" data-bind="foreach:thingList"><li data-bind="text:$data"></li></ul>
</div>
</div>
I am using Booststrap table to populate json data.
<!DOCTYPE html>
<html lang="en">
<title>
Boostrap Modal Example
</title>
<head>
<meta charset="utf-8">
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="bootstrap.js"></script>
<link rel="stylesheet" type="text/css" href="bootstrap.css">
<script type="text/javascript">
var data =
[
{
"id": 0,
"name": "test0",
"price": "$0"
},
{
"id": 1,
"name": "test1",
"price": "$1"
},
{
"id": 2,
"name": "test2",
"price": "$2"
},
{
"id": 3,
"name": "test3",
"price": "$3"
},
{
"id": 4,
"name": "test4",
"price": "$4"
},
{
"id": 5,
"name": "test5",
"price": "$5"
}
];
$(document).ready(function()
{
alert("I am ready");
$('#modalTable').on('shown',function()
{
console.log("I am in bro");
$('#mytable').bootstrapTable({
data: data
});
});
});
</script>
</head>
<body>
<button type="button" class="btn btn-info btn-lg" data-toggle="modal" data-target="#modalTable">Show Table</button>
<!-- Modal -->
<div id="modalTable" class="modal fade" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Modal Header</h4>
</div>
<div class="modal-body">
<table id="mytable" data-toggle="table" class="table">
<thead>
<tr>
<th class="col-xs-1" data-field="id">Id</th>
<th class="col-xs-1" data-field="name"> Name</th>
<th class="col-xs-2" data-field="price">Price</th>
</tr>
</thead>
</table>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</body>
</html>
I tried this also, but it dint work.
$(document).ready(function () {
alert("I am ready");
$('#modalTable').on('shown', function () {
console.log("I am in bro");
$('#mytable').bootstrapTable({
columns: [{
field: 'id',
title: 'Id'
}, {
field: 'name',
title: 'Name'
}, {
field: 'price',
title: 'Price'
}
],
data: [{
id: 1,
name: 'Item 1',
price: '$1'
}, {
id: 2,
name: 'Item 2',
price: '$2'
}, {
id: 2,
name: 'Item 2',
price: '$2'
}, {
id: 2,
name: 'Item 2',
price: '$2'
}, {
id: 2,
name: 'Item 2',
price: '$2'
}]
});
});
});
This is the out put I am getting
after clicking on the button modal popup pops up. but without data,
But it would be better If i can do it in first way.
I dont know where I am lacking. When I dont use modal. table works fine but as I include modal. it doesnt work.
Please help
DEMO
The problem was with 3 things:
I don't see the link to bootstraptable.css and bootstraptable.js in your html.
Bootstrap Modal event on open should be shown.bs.modal instead of just shown. So it would be
$('#modalTable').on('shown.bs.modal',function() instead of
$('#modalTable').on('shown',function()
Remove data-toggle from your table. It is not required there.
So below is the updated JS and HTML
JS
$('#modalTable').on('shown.bs.modal',function()
{
console.log("I am in bro");
$('#mytable').bootstrapTable({
data: data
});
});
HTML
<table id="mytable" class="table">
<thead>
<tr>
<th class="col-xs-1" data-field="id">Id</th>
<th class="col-xs-1" data-field="name"> Name</th>
<th class="col-xs-2" data-field="price">Price</th>
</tr>
</thead>
</table>
Plunker sample
How to hide table column if all json value is null for any property
using angular js
index.js
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
$scope.isArray = angular.isArray;
$scope.data = [{
"Id": null,
"Title": "US",
"Description": "English - United States",
"Values": [{
"Id": 100,
"LanId": 1,
"KeyId": 59,
"Value": "Save"
}]
}, {
"Id": null,
"Title": "MX",
"Description": "test",
"Values": [{
"Id": 100,
"LanId": 1,
"KeyId": 59,
"Value": "Save"
}]
}, {
"Id": null,
"Title": "SE",
"Description": "Swedish - Sweden",
"Values": [{
"Id": 100,
"LanId": 1,
"KeyId": 59,
"Value": "Save"
}]
}]
$scope.cols = Object.keys($scope.data[0]);
$scope.notSorted = function(obj) {
if (!obj) {
return [];
}
return Object.keys(obj);
}
});
index.html
<table border=1 style="margin-top: 0px !important;">
<thead>
<tr>
<th ng-repeat="(k,v) in data[0]">{{k}}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in data">
<td ng-repeat="(prop, value) in item" ng-init="isArr = isArray(value)">
<table ng-if="isArr" border=1>
<thead>
<tr>
<td>
<button ng-click="expanded = !expanded" expand>
<span ng-bind="expanded ? '-' : '+'"></span>
</button>
</td>
</tr>
<tr>
<th ng-repeat="(sh, sv) in value[0]">{{sh}}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="sub in value" ng-show="expanded">
<td ng-repeat="(sk, sv) in sub">{{sv}}</td>
</tr>
</tbody>
</table>
<span ng-if="!isArr">{{value}}</span>
</td>
</tr>
</tbody>
</table>
You can filter out columns that have only null values with:
JavaScript
$scope.cols = Object.keys($scope.data[0]).filter(function(col) {
return $scope.data.some(function(item) {
return item[col] !== null;
});
});
and check in template if this column should be rendered:
HTML
<table border=1 style="margin-top: 0px !important;">
<thead>
<tr>
<!-- Iterate over non-null columns -->
<th ng-repeat="col in cols">{{col}}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in data">
<!-- Use ngIf to hide redundant column -->
<td ng-if="cols.indexOf(prop)>=0" ng-repeat="(prop, value) in item" ng-init="isArr = isArray(value)" >
...
Plunker
http://plnkr.co/edit/PIbfvX6xvX5eUhYtRBWS?p=preview
So the id is null for every element in the array, then do
<th ng-repeat="(k,v) in data[0]" ng-show="v">{{k}}</th>
and
<td ng-repeat="(prop, value) in item" ng-init="isArr = isArray(value)" ng-show="value">
plnkr: http://plnkr.co/edit/rra778?p=preview
You need to make use of the cols property you defined in your $scope, but you also need to make sure its correct and responsive. You do that like this:
var colsFromData = function(data) {
var activeCols = {};
data.forEach(function(o) {
Object.keys(o).forEach(function(k) {
if(null == o[k])
return;
activeCols[k] = 1;
})
});
return Object.keys(activeCols);
}
$scope.cols = colsFromData($scope.data);
$scope.$watchCollection('data', colsFromData);
Then in your template, to use the now correct cols array:
...
<thead>
<tr>
<th ng-repeat="k in cols">{{k}}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in data">
<td ng-repeat="(prop, value) in item" ng-init="isArr = isArray(value)" ng-if="cols.indexOf(prop) >= 0">
...
And the updated plunker
I need to loop through .mainheader class to .mainheader because i need header class row and values class row value for grouping
This is my html
<table id="t01" cellspacing="0" cellpadding="0" class="table" style="margin-top:20px">
<thead>
<tr>
<th class="sorting">Group_Main_ID</th>
<th class="sorting">Group_Sub_ID</th>
<th class="sorting">Item</th>
<th class="sorting">Instructions</th>
<th class="sorting">Decision_Request_Input</th>
<th class="sorting">Status</th>
<th class="sorting">Evidence_Info</th>
<th class="sorting">Evidence_Doc</th>
</tr>
</thead>
<tfoot></tfoot>
<tbody id="editContents">
<tr id="1" class="mainheader " bgcolor="#000033">
<td id="nonEdit" class="th1 p_no" bgcolor="#215F8B">
<font color="white" align="left"></font>
</td>
<td class="th" bgcolor="#215F8B" align="left" style="color: white; display: table-cell;" colspan="7">
<font color="white" align="left"></font>
Header1</td>
</tr>
<tr id="2" class="header " bgcolor="#000033" style="opacity:0.8">
<td id="nonEdit" class="th1" bgcolor="#215F8B">
<font color="white" align="left"></font>
</td>
<td class="th" bgcolor="#215F8B" align="left" style="color: white; display: table-cell;" colspan="7">
<font color="white" align="left"></font>
SubHeader1</td>
</tr>
<tr class="values">
<td class="sno">1</td>
<td>1</td>
<td>4</td>
<td>1</td>
<td>2</td>
<td>1</td>
<td>null</td>
<td>Yes#No#NA</td>
</tr>
<tr class="values">
<td class="sno">1</td>
<td>1</td>
<td>4</td>
<td>1</td>
<td>2</td>
<td>1</td>
<td>null</td>
<td>Yes#No#NA</td>
</tr>
<tr class="values">
<td class="sno">1</td>
<td>1</td>
<td>4</td>
<td>1</td>
<td>2</td>
<td>1</td>
<td>null</td>
<td>Yes#No#NA</td>
</tr>
<tr id="2" class="header " bgcolor="#000033" style="opacity:0.8">
<td id="nonEdit" class="th1" bgcolor="#215F8B">
<font color="white" align="left"></font>
</td>
<td class="th" bgcolor="#215F8B" align="left" style="color: white; display: table-cell;" colspan="7">
<font color="white" align="left"></font>
Header1.2</td>
</tr>
<tr class="values">
<td class="sno">1</td>
<td>1</td>
<td>4</td>
<td>1</td>
<td>2</td>
<td>1</td>
<td>null</td>
<td>Yes#No#NA</td>
</tr>
<tr id="1" class="mainheader " bgcolor="#000033">
<td id="nonEdit" class="th1 p_no" bgcolor="#215F8B">
<font color="white" align="left"></font>
</td>
<td class="th" bgcolor="#215F8B" align="left" style="color: white; display: table-cell;" colspan="7">
<font color="white" align="left"></font>
Header2</td>
</tr>
<tr id="2" class="header " bgcolor="#000033" style="opacity:0.8">
<td id="nonEdit" class="th1" bgcolor="#215F8B">
<font color="white" align="left"></font>
</td>
<td class="th" bgcolor="#215F8B" align="left" style="color: white; display: table-cell;" colspan="7">
<font color="white" align="left"></font>
SubHeader2.1</td>
</tr>
<tr class="values">
<td class="sno">1</td>
<td>1</td>
<td>4</td>
<td>1</td>
<td>2</td>
<td>1</td>
<td>null</td>
<td>Yes#No#NA</td>
</tr>
</tbody>
</table>
My Javascript
var groupData = {};
var subGroupData = {};
var arr = [];
$('#t01 tbody tr.mainheader').each(function(i) {
var groupIdData ={};
groupIdData['id'] = $(this).attr('id');
groupIdData['name'] = $(this).find('td:eq(2)').text().trim()
groupIdData["action"]= 'Add/Edit/Delete'
//arr.push(garr)
groupData['group'] = groupIdData;
groupData['subgrps'] = [];
subGroupData = {};
subGroupData["action"]= 'Add/Edit/Delete'
subGroupData['id'] =$(this).next('.header').attr('id');
subGroupData['name']= $(this).next('.header').find('td:eq(2)').text().trim();
//arr.push(garr)
groupData['subgrps'].push(subGroupData)
subGroupData['items'] = [];
var items = [];
$(this).next('tr').each(function(){
if($(this).hasClass('values'))
{
var rowData = {};
$(this).find('td').each(function(i) {
var thh = $(this).closest('table').find('th').eq($(this).index()).text();
if(i == 0)
rowData["Action"]='Add/Edit/Delete'
if(i>1)
rowData[thh]=$(this).text().trim()
});
//arr.push(garr)
items.push(rowData)
}
else
return
});
//console.log('over')
}
subGroupData['items'].push(items);
groupData['subgrps'].push(subGroupData);
arr.push(groupData);
});
alert(JSON.stringify(arr)) ;
My Fiddle
https://jsfiddle.net/694kjj3o/
I am expecting JSON look like this
[
{
"group": {
"value": "Header1"
},
"subgrps": [
{
"name": {
"value": "SubHeader1.1"
},
"items": [
[
{
"value": {
"Group_Main_ID": 1,
"Group_Sub_ID": 5,
"Item": "4",
"Instructions": null,
"Decision_Request_Input": null,
"Status": null,
"Evidence_Info": null,
"Evidence_Doc": null
}
}
],
[
{
"value": {
"Group_Main_ID": 1,
"Group_Sub_ID": 5,
"Item": "4",
"Instructions": null,
"Decision_Request_Input": null,
"Status": null,
"Evidence_Info": null,
"Evidence_Doc": null
}
}
]
]
},
{
"name": {
"value": "SubHeader1.2"
},
"items": [
[
{
"value": {
"Group_Main_ID": 1,
"Group_Sub_ID": 5,
"Item": "4",
"Instructions": null,
"Decision_Request_Input": null,
"Status": null,
"Evidence_Info": null,
"Evidence_Doc": null
}
}
]
]
}
]
},
{
"group": {
"value": "Header2"
},
"subgrps": [
{
"name": {
"value": "Header2.1"
},
"items": [
[
{
"value": {
"Group_Main_ID": 1,
"Group_Sub_ID": 5,
"Item": "4",
"Instructions": null,
"Decision_Request_Input": null,
"Status": null,
"Evidence_Info": null,
"Evidence_Doc": null
}
}
]
]
}
]
}
]
I am unable loop it . Kindly guide me in this situation
Try
var arr = [];
$('#t01 tbody tr.mainheader').each(function (i) {
var $main = $(this),
main = {
"group": {
"value": $main.text().trim()
},
"subgrps": []
};
console.group($main.text().trim());
console.log(this);
$main.nextUntil('.mainheader', '.header').each(function () {
var $header = $(this),
header = {
"name": {
"value": $header.text().trim()
},
"items": []
};
console.group($header.text().trim());
console.log(this);
$header.nextUntil('.mainheader, .header', '.values').each(function (i) {
var $tr = $(this),
$tds = $tr.children(),
obj = {
"value": {
"Group_Main_ID": $tds.eq(0).text().trim(),
"Group_Sub_ID": $tds.eq(1).text().trim(),
"Item": $tds.eq(2).text().trim(),
"Instructions": null,
"Decision_Request_Input": null,
"Status": null,
"Evidence_Info": null,
"Evidence_Doc": null
}
};
console.group(i);
console.log(this);
header.items.push(obj);
console.groupEnd();
});
main.subgrps.push(header);
console.groupEnd();
});
arr.push(main);
console.groupEnd();
});
console.log(arr)
console.log(JSON.stringify(arr));
Demo: Fiddle
If you want to get dynamic key and values
var arr = [];
$('#t01 tbody tr.mainheader').each(function (i) {
var $main = $(this),
main = {
"group": {
"action":'Add/Edit/Delete',
"value": $main.text().trim()
},
"subgrps": []
};
//console.group($main.text().trim());
//console.log(this);
$main.nextUntil('.mainheader', '.header').each(function () {
var $header = $(this);
header = {
"name": {
"action":'Add/Edit/Delete',
"value": $header.text().trim()
},
"items": []
};
//console.group($header.text().trim());
//console.log(this);
$header.nextUntil('.mainheader, .header', '.values').each(function (i) {
var $tr = $(this);
obj = {};
obj.action = 'Add/Edit/Delete';
var sobj = {}
$tr.find('td').each(function (i) {
var thh = $(this).closest('table').find('th').eq($(this).index()).text();
sobj[thh] = $(this).text().trim()
});
obj.value = sobj;
//console.group(i);
//console.log(this);
header.items.push(obj);
//console.groupEnd();
});
main.subgrps.push(header);
//console.groupEnd();
});
arr.push(main);
//console.groupEnd();
});
//console.log(arr)
console.log(JSON.stringify(arr));
DEMO
https://jsfiddle.net/95nqr6op/6/
Your code is having extra closing curly bracket }.
I Updated the code. There are some errors I found on the console.
$('#t01 tbody tr.mainheader').each(function(i) {
var groupIdData = {};
groupIdData['id'] = $(this).attr('id');
groupIdData['name'] = $(this).find('td:eq(2)').text().trim()
groupIdData["action"] = 'Add/Edit/Delete'
//arr.push(garr)
groupData['group'] = groupIdData;
groupData['subgrps'] = [];
subGroupData = {};
subGroupData["action"] = 'Add/Edit/Delete'
subGroupData['id'] = $(this).next('.header').attr('id');
subGroupData['name'] = $(this).next('.header').find('td:eq(2)').text().trim();
//arr.push(garr)
groupData['subgrps'].push(subGroupData)
subGroupData['items'] = [];
var items = [];
$(this).next('tr').each(function() {
if ($(this).hasClass('values')) {
var rowData = {};
$(this).find('td').each(function(i) {
var thh = $(this).closest('table').find('th').eq($(this).index()).text();
if (i == 0)
rowData["Action"] = 'Add/Edit/Delete'
if (i > 1)
rowData[thh] = $(this).text().trim()
});
//arr.push(garr)
items.push(rowData)
} else
return
});
//console.log('over')
subGroupData['items'].push(items);
groupData['subgrps'].push(subGroupData);
arr.push(groupData);
});