table in Angular using dynamic table headers - javascript

I was creating an angular app to display data from various data sources. I configured the list of various data sources in a JSON file each data source has a set of values attached to it.
Here is an example
var configurableConfigurations=[
{
name:"Locations",
table:"location_set",
columnList:[
{
name:"LOCATION_NAME",
alias:"Location",
primary:true
},
{
name:"DESCRIPTION",
alias:"Description",
primary:false
}
]
},
{
name:"System Parameters",
table:"system_params",
columnList:[
{
name:"param_Key",
alias:"Parameter",
primary:true
},
{
name:"param_Value",
alias:"Value",
primary:false
}
]
}
];
I then created an HTML page to display this using angular : the page has 2 parts
1. A select box which shows various parameters this is done using ng-repeat
<select name="ConfigurationName" ng-model="selected" ng-options="eachConfiguration.name for eachConfiguration in configurableConfigurations" ng-change="fetchRequiredConfiguration()">
A table which I want to generate using the headers of the parameter selected
this is my code to do that
<table id="configtable">
<thead>
<tr>
<th class="col-md-1" ng-repeat="column in selected.columnList" >{{column.alias}}</th>
</tr>
</thead>
This works great for the first time. But when the option is selected again using the select box the table header is not shown.
The table data is being populated properly , its just the table headers that are getting messed up.
Could anyone please help me get around this problem. I am new to angularjs. May be I am missing something important.
Edit ::
I should Also Mention that I fetch the data from the API and then was using the Data table plugin(https://www.datatables.net/download/) to show this as Data
$("#configtable").DataTable({
"ajax": "../fetchvalue/config/"+this.selected.table,
destroy: true,
"columns":{ "data": "ColumnXXX"},
{"data": "ColumnYYY" }
});
As it turns out, I have a problem with the disappearing headers only when I use the DataTable

I don't know how the table data is store but this way is good:
$scope.configurableConfigurations = [{
name: "Locations",
table: "location_set",
columnList: [{
name: "LOCATION_NAME",
alias: "Location",
primary: true
}, {
name: "DESCRIPTION",
alias: "Description",
primary: false
}],
data:[[12,"home"],[43,"work"]]
}, {
name: "System Parameters",
table: "system_params",
columnList: [{
name: "param_Key",
alias: "Parameter",
primary: true
}, {
name: "param_Value",
alias: "Value",
primary: false
}],
data:[["GOO",586],["FOO",123]]
}];
And then you can print the table like this:
<select name="ConfigurationName" ng-model="selected" ng-options="eachConfiguration as eachConfiguration.name for eachConfiguration in configurableConfigurations" ng-change="fetchRequiredConfiguration()"></select>
<table id="configtable">
<thead>
<tr>
<th class="col-md-1" ng-repeat="column in selected.columnList">{{column.alias}}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in selected.data" >
<td class="col-md-1" ng-repeat="col in row">{{col}}</td>
</tr>
</tbody>
</table>
Example here

Related

Space between data when exporting excel file from datatables

I have this bug on my export file using Datatables. There are some unnecessary space between the data.
<script>
$(document).ready(function () {
$('.dataTablesWExport').DataTable({
dom: 'Bfrtip',
buttons: [{
extend: 'excelHtml5',
exportOptions: {
columns: ':visible'
}
},
{
extend: 'pdfHtml5',
exportOptions: {
columns: ':visible'
}
},
'colvis'
],
"order": []
});
});
</script>
Screeshot of the export file
https://i.stack.imgur.com/X4gah.png
You can use a row function to control which rows are exported (the rows with data) and which are not (the blank rows).
Example
Assume I have the following data in my table:
<table id="myTable" class="display nowrap dataTable cell-border" style="width:100%">
<thead>
<tr>
<th>Name</th>
<th>Position</th>
<th>Office</th>
</tr>
</thead>
<tbody>
<tr>
<td>Adélaïde Fleury</td>
<td>System Architect</td>
<td>Paris</td>
</tr>
<tr>
<td>John Smith</td>
<td>Accountant</td>
<td>London</td>
</tr>
<tr>
<td></td>
<td></td>
<td>Tokyo</td>
</tr>
</tbody>
</table>
My DataTable object is defined like this:
$('#myTable').DataTable( {
dom: 'Bfrtip',
buttons: [
{
extend: 'excel',
exportOptions: {
columns: [ 0, 1 ], // just for my demo
rows: function ( idx, data, node ) {
return data[0];
}
}
}
]
} );
This is displayed as follows:
It uses a rows function to test each row. If the first cell in the row (data[0]) has data in it, then the row will be exported to Excel. But if the cell is blank, empty, or null, the row will not be exported:
How It Works
The row function returns a value of true or false for each row in the DataTable. JavaScript will therefore treat a non-blank value in data[0] as truthy - and therefore that row is returned.
So, return data[0] is just a more compact way of writing this:
if ( data[0].length > 0 ) {
return true;
} else {
return false;
}
Data Arrays vs Data Objects
My source data was taken directly from the HTML table, so it was provided as arrays of data (one array for each row): [ 'John Smith', 'Accountant' ]. This is why I used data[0] to check the contents of the first cell in each row.
If my data had been sourced from a JSON object, it may have looked different, for example:
{
"name": "John Smith",
"position": "Accountant"
},
{
...
}
In this case, data[0] would not work. I would need to use data.name instead.

How to reload table data using DataTables, Ajax call & Json response?

I have a table that is generated through Thymeleaf. I would like to refresh the contents of the table using jQuery.
<table class="table table-hover" id="main-table">
<thead class="thead-inverse">
<tr>
<th class="col-md-2 text-center">Network Id</th>
<th class="col-md-2 text-center">Rep date</th>
<th class="col-md-2 text-center">Hashrate [KH/s]</th>
</tr>
</thead>
<tbody>
<tr th:each="networkHashrate : ${networkHashrates}" th:onclick="'javascript:openPoolModal(\''+ ${networkHashrate.id} + '\');'">
<td class="text-center" id="hashrateId" th:text="${networkHashrate.id}"> Sample id</td>
<td class="text-center" id="repDate" th:text="${#findAndDisplayDataService.formatDate(networkHashrate.repDate)}">Sample rep-date</td>
<td class="text-center" id="hashrate" th:text="${#findAndDisplayDataService.formatHashrate(networkHashrate.hashrate)}">Sample hashrate</td>
</tr>
</tbody>
</table>
I have come up with such function to update table contents every 8s:
$(document).ready(function() {
var table = $('#main-table').DataTable({
ajax: {
url: '/refresh',
dataSrc:''
},
paging: true,
lengthChange: false,
pageLength: 20,
stateSave: true,
info: true,
searching: false,
"aoColumns": [
{ "orderSequence": [ "asc", "desc" ] },
{ "orderSequence": [ "asc", "desc" ] },
{ "orderSequence": [ "desc", "asc" ] }
],
"order": [[ 0, "asc" ]]
});
setInterval(function(){
table.ajax.reload();
}, 8000);
});
Here's the JSON response:
[{
"id":1,
"repDate":{
"offset":{ },
"nano":880042000,
"year":2018,
"monthValue":4,
"dayOfMonth":25,
"hour":12,
"minute":58,
"second":53,
"month":"APRIL",
"dayOfWeek":"WEDNESDAY",
"dayOfYear":115
},
"hashrate":5114926.0
},...more entries
]
An empty table prints and I keep getting an error:
Uncaught TypeError: Cannot read property 'reload' of undefined
There's also an alert pop-up saying:
Data Tables warning: table id=main-table - Requestem unknown parameter '0' for row 0 column 0. For more information about this error, please see: http://datatables.net/tn/4
EDIT
I moved table declaration outside the function. Now I just keep getting the warning.
EDIT 2
I did as you stated, the data keeps refreshing, but there are still few issues.
First of all, my stateSave: true property stopped working, so when the table is reloaded it always gets back to the first page.
Secondly, I lost all my styling (class="text:center" for example) and on:click property that were originally in my html file.
Try to declare the table before the $(document).ready :
var table;
$(document).ready(function() {
table = $('#main-table').DataTable({"serverSide": true, ...})
setInterval(function(){
table.ajax.reload();
}, 8000);
})
The error is related to your column definition, try this way to define columns :
"columnDefs": [
{
"targets": 0,
"data": "id",
},
{
"targets": 1,
"data": "repDate",
},
{
"targets": 2,
"data": "repDate",
}
]

Reload dataTable from variable

I searched all over web and I didn't find easy solution for this. I'm using jQuery DataTables with "static" data source (one var is filled with data using SignalR and then later, DataTable is built). Now, when change of this dataset comes, I want to update table using this data set. Ideally, that would be simple "refresh" which reloads data from specified source. Here is my HTML
<table class="table table-hover table-condensed table-responsive" id="tableAccounts">
<thead>
<tr>
<th data-localize="_A_C">_A_C</th>
<th data-localize="_Name">_Name</th>
<th data-localize="_Address">_Address</th>
<th data-localize="_City">_City</th>
<th data-localize="_Phone">_Phone</th>
</tr>
</thead>
<tbody></tbody>
And here is my javascript which initially loads data:
tAccounts = $('#tableAccounts').dataTable({
"data": AccountAll,
"bFilter": true,
"pageLength": 100,
"bSearchable": true,
"bInfo": false,
"columns": [
{ "data": "AccountCode" },
{ "data": "Name" },
{ "data": "Address" },
{ "data": "City" },
{ "data": "Phone" }
],
"columnDefs": [
{
"render": function (data, type, row) {
return ("0000" + data.toString(16)).slice(-4);
},
"targets": 0
},
{ "visible": true, "targets": [0] }
]
});
tl;dr;
How to refresh datatable when data source (AccountAll in this case) is changed without destroying whole table? Bonus point if selection and filter is preserved.
Change can be anything. New row added, row removed, cell value changed.
You can use combination of clear() and rows.add() API methods to clear existing data and add updated data.
In this case filtering and sorting would be preserved.
If you want to preserver the current page, call draw(false) instead of draw() but if you're adding new rows, there is little sense in preserving the current page
For example:
var data = [['old',2,3,4,5,6]];
var table = $('#example').DataTable({
'data': data
});
var dataNew = [['new',2,3,4,5,6]];
table.clear().rows.add(dataNew).draw();
See this example fro code and demonstration.

Unable to display data using jQuery datatables, AJAX and JSON

I'm having a problem displaying my data on my jQuery DataTable using AJAX. I'm using the library from datatables.net. I've tried packaging the JSON in many different formats and nothing is working. I've also messed around with the 'columns' section, interchanging 'title' and 'data.' I only have one event to display for now, but the bottom of the table shows something crazy like 4,000 entries. Here is my code:
<script src="//cdn.datatables.net/1.10.10/js/jquery.dataTables.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$('#myTable').DataTable({
"processing": true,
"ajax": {
"url": "/api/EventsApi/GetAll",
"dataSrc": ""
},
columns: [
{ title: "Title" },
{ title: "Template" },
{ title: "Capacity" },
{ title: "Boarding Location" },
{ title: "Status" },
{ title: "Edit / Delete" }
//{ "data": "title" },
//{ "data": "eventTemplateID" },
//{ "data": "locomotive.capacity" },
//{ "data": "boardingLocationStart.city" },
//{ "data": "status" },
//{ "data": "status" }
]
});
});
<div class="title-content">#ViewBag.Title</div>
<div id="dataTable">
<table id="myTable" class="table table-hover" style="text-align: center;">
<tbody id="tBody">
<!-- Table body data goes here -->
</tbody>
</table>
</div>
Here is the JSON that's being returned from the AJAX call:
{"data":[{"tripEventID":1,"extraDetails":"this train has special details","eventName":"ZombieTrainEventName ","departureDate":"\/Date(1443715200000)\/","returnDate":"\/Date(1443718800000)\/","eventCapacityOveride":100,"eventTemplateID":3,"title":"The Zombie Train ","companyID":1,"description":"description of zombie train ride ","boardingClosed":30,"status":1,"boardingLocationStart":{"boardingLocationID":3,"companyID":1,"name":"Skunk Train Willits","streetAddress":"Willits somewhere","city":"Some city","state":"CA","zip":"95713","description":"Desc field1"},"boardingLocationStartTo":{"boardingLocationID":3,"companyID":1,"name":"Skunk Train Willits","streetAddress":"Willits somewhere","city":"Some city","state":"CA","zip":"95713","description":"Desc field1"},"boardingLocationReturnFrom":{"boardingLocationID":3,"companyID":1,"name":"Skunk Train Willits","streetAddress":"Willits somewhere","city":"Some city","state":"CA","zip":"95713","description":"Desc field1"},"boardingLocationReturnTo":{"boardingLocationID":3,"companyID":1,"name":"Skunk Train Willits","streetAddress":"Willits somewhere","city":"Some city","state":"CA","zip":"95713","description":"Desc field1"},"allowFlexableReturnDate":false,"product":[],"productBundle":[{"bundleID":10,"companyID":1,"displayName":" Pumkin Bundle copy Test","price":0.0100,"tax":0.0200,"productList":[]}],"locomotive":{"trainID":1,"companyID":1,"title":"Skunk_Steam ","type":1,"description":"Steam locomotive ","capacity":998,"status":0},"media":{"mediaID":1,"companyID":1,"hero":[],"gallery":[{"mediaDetailID":6,"formatTypeID":2,"fileName":"testimage6.txt","order":1,"path":null,"url":null},{"mediaDetailID":7,"formatTypeID":2,"fileName":"testimage6.txt","order":1,"path":"path6","url":"url6"},{"mediaDetailID":8,"formatTypeID":2,"fileName":"testimage7.txt","order":1,"path":"path7","url":"url7"}],"inside":[{"mediaDetailID":1,"formatTypeID":1,"fileName":"testimage.txt","order":1,"path":null,"url":null},{"mediaDetailID":2,"formatTypeID":1,"fileName":"testimage2.txt","order":1,"path":null,"url":null},{"mediaDetailID":3,"formatTypeID":1,"fileName":"testimage3.txt","order":1,"path":null,"url":null}]},"duration":15,"isExclusive":false,"timeAtDestination":45,"isOneWay":false}]}
Like I said, I've tried repackaging the JSON as nested objects and arrays with nothing working. Am I missing something obvious? Any help is appreciated, thank you!
You have to name the columns in your js like the json index keys like this:
$(document).ready(function() {
$('#myTable').DataTable( {
"ajax": "path/to/your/file.json",
"columns": [
{ "data": "title" },
{ "data": "eventTemplateID" },
{ "data": "eventCapacityOveride" },
{ "data": "boardingLocationStart.streetAddress" },
{ "data": "status" },
{ "data": null }
],
"columnDefs": [ {
"targets": -1,
"data": null,
"defaultContent": "<button>Click!</button>"
} ]
} );
} );
Note that you can define custom data in tables with the columnDefs option.
And than edit your HTML with something like this:
<table id="myTable" class="table table-hover" style="text-align: center;">
<thead>
<tr>
<th>Title</th>
<th>Template</th>
<th>Capacity</th>
<th>Boarding location</th>
<th>Status</th>
<th>Edit / Delete</th>
</tr>
</thead>
<tfoot>
<tr>
<th>Title</th>
<th>Template</th>
<th>Capacity</th>
<th>Boarding location</th>
<th>Status</th>
<th>Edit / Delete</th>
</tr>
</tfoot>
</table>
Here you can find a working fiddle

Generate table body rows using ng-repeat

I'm using Smart Table (latest version) and AngularJs (v. 1.2.16) to build a table using two objects, one for the header and the other for the table content. My problem happens when creating the table body cells. Using the following code works fine:
<tr ng-repeat="row in rowCollection">
<td>{{row.productNumber}}</td>
<td>{{row.BuyIt}}</td>
<td>{{row.brand}}</td>
</tr>
But I need to generate the body like this:
<tr ng-repeat="row in rowCollection">
<td ng-repeat="col in columns">{{value-to-show}}</td>
</tr>
My object is this:
$scope.rowCollection = [{
"productNumber": 5877,
"BuyIt": "Online",
"brand": "BrandA"
}, {
"productNumber": 5743,
"BuyIt": "Online",
"brand": "BrandB"
}];
$scope.columns = [{
'colName': 'Product Number',
'Id': 'column1',
'className': '',
'skipNatural': true,
'sortDefault': 'reverse'
}, {
'colName': 'Store or Online',
'Id': 'column2',
'className': '',
'skipNatural': true
}, {
'colName': 'Brand',
'Id': 'column3',
'className': '',
'skipNatural': true
}];
How can I get the right value to appear in the right cell?
I have a jsfiddle that shows the problem: http://plnkr.co/edit/aEfzzU?p=preview
Any help is really appreciated.
You can change your ng-repeat to this:
<tbody>
<tr ng-repeat="row in rowCollection">
<td ng-repeat="(key, value) in row">{{value}}</td>
</tr>
</tbody>
You may also extend your column objects with which property it corresponds with like this:
<tr ng-repeat="row in rowCollection">
<td ng-repeat="col in columns">{{row[col.property]}}</td>
</tr>
This will also have the nice side effects of:
You may in your header use the st-sort directive on col.property to enable sorting
Dynamically change which columns to display
Use your column objects as a configuration for both header and body
Use on complex objects which contains more properties than you care to show!

Categories

Resources