How to use DataTables in case of dynamic rows? - javascript

I'm new to the concept of DataTables and I'm referring to this example.
The only difference in my case is that my HTML table is dynamic. HTML code for my table is as follows:
<table id="table_id">
<thead>
<tr>
<th>Column 1</th>
<th>Column 2</th>
<th>Column 3</th>
</tr>
</thead>
</table>
In my script tag I dynamically add rows to this table using insertRow() method and fetching data from a local json file as follows:
var DemoTable = document.getElementById("table_id");
var DemoRow, DemoCell1, DemoCell2, DemoCell3;
$("#table_id").find("tr:gt(0)").remove(); //to keep the first row headings as set in the html code
for(var i=0; i<DemoData.length; i++) //DemoData contains the fetched json data
{
var DemoRow = DemoTable.insertRow();
DemoCell1 = DemoRow.insertCell(0);
DemoCell2 = DemoRow.insertCell(1);
DemoCell3 = DemoRow.insertCell(2);
DemoCell1.innerHTML = DemoData[i]["Data1"];
DemoCell2.innerHTML = DemoData[i]["Data2"];
DemoCell3.innerHTML = DemoData[i]["Data3"];
}
Also, I've included jquery.dataTables.min.js and dataTables.bootstrap.min.js in the same order.
After this, I've added:
$(document).ready(function() {
$('#table_sub_id').DataTable();
} );
I get the following error:
Uncaught TypeError: Cannot read property 'pageButton' of undefined
Please help. Thanks :)

Instead of this you can use this:
$('#table_id').DataTable( {
"ajax": "data/objects.txt",
"columns": [
{ "data": "cell1" },
{ "data": "cell2" },
{ "data": "cell3" }
]
});

Related

Getting data from JSON and formatting this into a table

I am getting a little stuck with this one. I am trying to use javascript on my website to convert my API JSON data to a table. Without using an array in an array of data in JSON, it works fine which each item on a new line but soon as I use an nested array of data in there, it has all the data on one line, seperated by a comma. Thinking a for loop would work here but i'm not 100% sure if this is the best method.
I have tried multiple searches online and tested around myself but I can't seem to get it to work.
The following is simple version of the JSON data I am working with:
MACLIST = ["ABC","DEF"]
IPLIST = ["10.10.10.10","20.20.20.20"]
ZONELIST = ["Inside","Outside"]
var json = [{"MAC":MACLIST,"IP":IPLIST,"ZONE":ZONELIST},{"SOMETHING ELSE":"OK"}];
Script used:
$(document).ready(function () {
ko.applyBindings({
teams: json
});
});
HTML used:
<table>
<thead>
<tr>
<th>Device</th>
<th>IP</th>
<th>Zone</th>
</tr>
</thead>
<tbody data-bind="foreach: teams">
<tr>
<td data-bind="text: MAC"></td>
<td data-bind="text: IP"></td>
<td data-bind="text: ZONE"></td>
</tr>
</tbody>
</table>
Working JSON version (without nested array data) works:
var json = [{"MAC":"ABC","IP":"10.10.10.10","ZONE":"Inside"},{"MAC":"DEF","IP":"20.20.20.20","ZONE":"Outside}];
Any tips or advice would be greatly appreciated
Testing URL JSFiddle Link
You can map over each row to create a string of html for each row. Then inside each row, map over each column to create the string of html for each cell.
var json = [{
"MAC": "ABC",
"IP": "10.10.10.10",
"ZONE": "Inside"
}, {
"MAC": "DEF",
"IP": "20.20.20.20",
"ZONE": "Outside"
}];
const makeCell = (content) => {
return `<td>${content}</td>`
}
const makeRow = (content) => {
return `<tr>${content}</tr>`
}
const table = document.querySelector('.table')
const colHeaders = Object.keys(json[0]).map(key => makeCell(key)).join('')
const bodyRows = json.map(row => {
return makeRow(Object.keys(row).map(col => makeCell(row[col])).join(''))
}).join('')
document.querySelector('thead tr').innerHTML = colHeaders
document.querySelector('tbody').innerHTML = bodyRows
<table>
<thead>
<tr></tr>
</thead>
<tbody>
</tbody>
</table>
Hopefully this article will help you resolve the problem
https://www.geeksforgeeks.org/how-to-convert-json-data-to-a-html-table-using-javascript-jquery/

vuetify simple table. Convert nested object propertied to <td> columns

I am using vuetify 2.1 and a simple nested table. with the following data structure in my data model:
groups:[
{
style:"X",
colours:"colours",
sizes:"standard",
marketplaces:[
{
markeplace:"UK",
pricelists:["A","B","C"]
},
{
markeplace:"EU",
pricelists:["D","E","F"]
},
{
markeplace:"ROW",
pricelists:["G","H","I"]
},
]
},
{
style:"X",
colours:"Black/White",
sizes:"standard",
marketplaces:[
{
markeplace:"UK",
pricelists:["X","Y","Z"]
},
{
markeplace:"EU",
pricelists:["P","Q","R"]
},
{
markeplace:"ROW",
pricelists:["S","T","U"]
},
]
}
]
What I want to achieve is < td > records for:
style
colour
size
UK.pricelists[0]
UK.pricelists[1]
UK.pricelists[2]
EU.pricelists[0]
EU.pricelists[1]
EU.pricelists[2]
ROW.pricelists[0]
ROW.pricelists[1]
ROW.pricelists[2]
<v-simple-table
dense
calculate-widths
fixed-header
height="90vh"
>
<template v-slot:default>
<thead>
<tr>
<th>Style</th>
<th>Colour Group</th>
<th>Size Group</th>
<th>UK 1</th>
<th>UK 2</th>
<th>UK 3</th>
<th>EU 1</th>
<th>EU 2</th>
<th>EU 3</th>
<th>ROW 1</th>
<th>ROW 2</th>
<th>ROW 3</th>
</tr>
</thead>
<tbody>
<tr v-for="group in groups" >
<td>{{group.style}}</td>
<td>{{group.colour}}</td>
<td>{{group.size}}</td>
<!-- this is where I am struggling... I need the next 9 td records to iterate through two levels of arrays. -->
<td v-for="mkt in group.marketplaces">{{mkt.pricelists[0]}}<td>
</tr>
</tbody>
</template>
</v-simple-table>
for reference I have complete control over the API and the shape of the data object so feel free to suggest an alternative document structure. Can you native iterate over multiple levels in vuetify simple table - perhaps using array.foreach().
Is there a vue equivalent of react-fragment which acts as outer nesting element but does not actually render anything. The challenge is that this is within a table row and I need a collection around only some of the cells in the row.
do I move the logic to a method which remaps the pricelists for the passed in group. In my situation, all groups will have the same marketplaces in the same order and each marketplace will have the same number of price lists so I don't have any issues with sorting or padding the array.
In the absence of any other suggestions, I have create a method to remap the data into a single array:
methods: {
remapPricelists(style,colours,sizes){
/* This should find a single match */
let group = this.groups.filter(g=>{
return g.style == style
&& g.colours == colours
&& g.sizes == sizes
});
let pl =[];
group[0].pricelists.map(plst =>{
pl = pl.concat(plst.pricelists);
});
return pl;
}
}
DISCLAIMER: I have edited the above code from my live data which has a slightly different format (more outer groups and differently named fields) so E&OE. In production, I will likely abstract the group fetch to a separate method as I am going to need it in lots of places and will likely strip the outer array to just leave the group object so that I can access the inner data without having to specify the group array-index.

Dynamic JSON object to Html Table

I have gone through this solution Parsing JSON objects for HTML table . But in this solution Object keys are pre-defined when creating table. But I have some json data which can have random data.
Somtimes it can be :
var data = {
"C#": 2172738,
"CSS": 9390,
"HTML": 135085,
"Java": 337323
}
Or, Sometimes it can be:
var data = {
"Go": 2172738,
"Ruby": 9390,
"Dart": 135085
}
That means keys are not fixed. That data object can be dynamic. I want to convert the dynamic object to html table. Let's say, I have a table where thead is defined and tbody is empty:
<table id="_myTable">
<thead>
<th>Language</th>
<th>Line of Codes</th>
</thead>
<tbody>
</tbody>
</table>
How should I approach to insert that dynamic object data to tbody.
You can use for...in, Template literals and element.insertAdjacentHTML(position, text); to accomplish your task:
var data = {
"C#": 2172738,
"CSS": 9390,
"HTML": 135085,
"Java": 337323
}
for (key in data) {
var tr = `<tr><td>${key}</td><td>${data[key]}</td></tr>`;
document.querySelector('#_myTable tbody').insertAdjacentHTML('beforeend', tr);
}
<table id="_myTable">
<thead>
<th>Language</th>
<th>Line of Codes</th>
</thead>
<tbody>
</tbody>
</table>
You can use Object.keys(data) to get all of keys for "language" table data and Object.values(data) or Object.keys(data).map(key => data[key]) for "line of codes" table data.

How to append jquery stringyfy data to table with editable (tr and td) data of 4 users one by one like loop

I am getting json.stringyfy data and want to append all json.stringyfy data to table,with each tr editable but I don't know that much part of jquery so unable to get any idea can anyone tell me what should do to achieve this?
Json data got in response
[{"id":"1","name":"abc"}, user id 1 data
{"id":"2","name":"def"}, user id 2 data
{"id":"3","name":"xyz"}, user id 3 data
{"id":"4","name":"aaa"}] user id 4 data
Ajax call with success function to handle stringyfy data
$.ajax({
url: "<?= base_url('Test_controller/show_user') ?>",
type: 'POST',
data: {
},
success: function (response) {
var myJSON = JSON.stringify(response);
// code Here to append data in table one by one with content editable tr
}
});
Html table
<table class="show_data">
<tr>
<th>User id</th>
<th>User name</th>
</tr>
</table>
Just take your data and append it to the table. Loop through each entry in your data and (if using jquery) do .append(). I just create a simple variable with your json but you can do this with your myJSON variable inside of the success function.
var data = [{"id":"1","name":"abc"},
{"id":"2","name":"def"},
{"id":"3","name":"xyz"},
{"id":"4","name":"aaa"}]
data.forEach(user => {
$('.show_data').append(`<tr><td>${user.id}</td><td>${user.name}</td></tr>`);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table class="show_data">
<tr>
<th>User id</th>
<th>User name</th>
</tr>
</table>
Edit
You are getting that in error because you are using JSON.stringify which makes your json a string. You can't iterate on a string. Just use response instead of JSON.stringify(response);
You may use jQuery.each() and build elements on the fly:
var myJSON = [{"id": "1", "name": "abc"},
{"id": "2", "name": "def"},
{"id": "3", "name": "xyz"},
{"id": "4", "name": "aaa"}];
$.each(myJSON, function (idx, ele) {
$('.show_data tbody').append(
$('<tr/>') // create a TR
.append($('<td/>', {text: ele.id})) // append the first TD
.append($('<td/>', {text: ele.name})) // append the second TD
);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table class="show_data">
<thead>
<th>User id</th>
<th>User name</th>
</thead>
<tbody>
</tbody>
</table>

ng-Show records of table on condition

I am trying to show rows and their sum of value of columns. It has three states on which condition held.
1) auto
2) live
3) autolive (not present in json, need auto and live combine in rows)
Conclusion:
On siteData.jobType==toggleValue if (toggleValue==auto ), it shows records of "auto"
On siteData.jobType==toggleValue (toggleValue==live ), it shows records of "live"
But on siteData.jobType==toggleValue (toggleValue==autolive ), it shows no record , coz autolive is not present in json
How can I achieve it to show combine records of auto and live?
// custom toggle button https://github.com/tannerlinsley/nz-toggle
<nz-toggle
tri-toggle
on-toggle="myFunction()"
ng-model="toggleValue"
val-true="'auto'"
val-false="'live'"
val-null="'autolive'">
</nz-toggle>
<table class="table table-condensed" border ="1" >
<thead>
<tr>
<th>PiteId</th>
<th>PiteId</th>
<th>Type</th>
<th>Date</th>
<th >Success</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="siteData in siteObject" ng-show="siteData.jobType==toggleValue" >
<td>{{siteData.sid}}</td>
<td>{{siteData.PiteId}}</td>
<td>{{siteData.Type}}</td>
<td>{{siteData.Date}}</td>
<td ng-init="siteObject.total.siteData.countSuccess = siteObject.total.siteData.countSuccess + siteData.countSuccess">{{siteData.countSuccess}}</td>
</tr>
</table>
json format
siteObject =
{
"data": [
{
"sid": 1,
"PiteId": "1~10-4-2017~15:13:40",
"Type": "live",
"Date": "2017-04-14T18:30:00.000Z",
"countSuccess": 1
},
{
"sid": 1,
"PiteId": "1~10-4-2017~15:13:40",
"Type": "auto",
"Date": "2017-04-14T18:30:00.000Z",
"countSuccess": 1
}
]
}
I want all of them when i toggle autolive
try this workaround: ng-show="toggleValue.indexOf(siteData.jobType) > -1"
You need to create a custom filter function like this: (can be named anything)
<tr ng-repeat="siteData in siteObject.data | filter: customFilter">
And, in your controller, you can implement some custom logic for that. Something like this:
$scope.customFilter = function(obj) {
if($scope.toggleValue !== 'autolive') {
return obj.Type === $scope.toggleValue
}
return true;
}
That should do it!
Here's working codepen example

Categories