DataTable getting deformed after the update from Axios get call - javascript

I have a data table for which I am doing an Axios get call and populating the tbody. As per observation, it is getting deformed (pagination not working, also if new data is just 10 rows, it shows 100 row. [Before update of 10 rows it was 100 rows so somehow data table not getting reinitialized])
This is my JavaScript which is updating tbody
<pre>
<script>
var sitename = "{{data.site.name | safe}}"
var avm = document.getElementById("ravm");
function loadAvm() {
axios.get('ravm', {
params: {
site: sitename
}
}).then(function (resp) {
console.log(resp.data.length);
avm.innerHTML = resp.data;
}).catch(function (err) {
console.log(err)
})
}
setInterval(function () {
loadAvm();
}, 3000);
</script>
</pre>
My Django template is below
{% for key, value in data.alerts.items%}
<tr>
<td class="text-{{value.severity}}">{{value.timestamp}}</td>
<td class="text-{{value.severity}}">{{value.message_text}}
</td>
</tr>
{% endfor %}
PS: Everything is working fine if I don't do this Axios call to update and just refresh pages to get new data from the view.

after a lot of research i was able to find my answer
table = $('#example1').dataTable();
oSettings = table.fnSettings();
table.fnClearTable(this);
table.DataTable().destroy();
table.find('tbody').append(resp.data);
table.DataTable({
"responsive": true,
"autoWidth": false,
"ordering": false,
"info": true,
"pageLength": 10,
"bDestroy": true,
"recordsFiltered": 10,
}).draw();

Related

Laravel Yajra datatables user input values updating database values

im working on a databtable thats displaying data from my sql table. so far everything is displaying great however one of my fields needs to be able to be edited by the user and have that value updated in the database accordingly. I've been looking into multiple ways to do this but they havent been working. I've looked into form inputs,cell().edit() and onBlur from https://datatables.net but havent been able to get them to work. currently i have this for my script.
$(document).ready(function () {
var table = $('#example').DataTable({
serverSide: false,
language: {
searchBuilder: {
title: 'Custom Filter'
}
},
dom: 'Q<"pull-left"f><"pull-right"l>rtip',
ajax: {
url: "{{ url('/test') }}",
type: "GET",
datatype: "text",
data: {
q:"select * from exampleTable",
filename:"examplefile.json",
cacheInterval: 1
}
},
columns: [
{data: 'column1',title: 'column1'},
{data: 'column2',title: 'column2'},
{data: 'column3',title: 'column3'
"fnCreatedCell": function (nTd, oData) {
$(nTd).html("<input class='form-control' id='userInput' value='"+ oData.column3 +"'>");
}},
],
order: [
[0, 'asc']
],
column3 in this case would be the one that shows as form field showing the current data already filled as default but can be changed.
my html is in a separate blade with this.
<div class="card">
<div class="card-header">Test Table</div>
<div class="card-body">
<button class="updatebutton"type="submit">Submit</button>
<table id="example" class="table table-striped">
</table>
</div>
</div>
preferably It works like onBlur where they edit the line and as soon as they click off it updates the cell however I'll also take updating off the button click.

refresh pagination laravel with axios and datatables

I'm creating a list user table on fw laravel by using datatable and axios (not use vuejs), i don't use datatable's pagination but laravel's one because datatables take a lot of time to respond upon retrieving a million records, I can't find a way to use serverside feature cause axios replace ajax feature in severside. The issue began from this:
I'm successful to use laravel's pagination with js but as it comes to 10 or more page, the pagination not update and change the positive upon i click number page, i only can change a page from 1 to 10, here is my pagination code:
display pagination
<div id="pagination">
{!! $axios->links() !!}
</div>
and here is js code
$(document).on('click', '.pagination a',function(e) {
e.preventDefault();
$('li').removeClass('active');
$(this).parent().addClass('active');
let pg = $(this).attr('href')
reloadData(pg)
window.history.pushState("", "",pg)
})
reloadData function:
function reloadData(value){
axios.get(url+'/data'+ value).then(handleResponse)
.catch(function (error) {
console.log(error);
})
function handleResponse(response) {
data = response.data.data;
$('#dataid').DataTable().clear().destroy()
$('#dataid').DataTable({
paging : false,
severSide: true,
processing: true,
deferRender: true,
order: [],
retrieve: true,
pagingType: 'full_numbers',
dom: 'lBfrtip',
columnDefs: [{
"defaultContent": "-",
"targets": "_all"
}],
data: data,
columns: [
{ data: 'name' },
{ data: 'email' },
{ data: 'phone' },
{ data: '' },
{ data: 'created_at' },
{ data: function(data){
return '<td class="pr-0 text-center">'+
'<a id="delete-btn" class="label label-inline label-light-default font-weight-bolder delete-btn" data-id="'+data.id+'" href="javascript:void(0)">Delete'+
'</a>'+ '/'+
'<a id="edit-btn" class="label label-inline label-light-default font-weight-bolder delete-btn" data-id="'+data.id+'" href=" javascript:void(0)">Edit'+
'</a>'+
'</td>'
}}
],
})
}
}
controller :
//display view and pagination
public function index(Request $request)
{
$axios = Apiato::call('User#GetAllUsersAction', [$request]);
$axios->withPath('');
return view('user::Axios.list',compact('axios'));
}
// i retrived the records from this
public function getData(Request $request)
{
//$user = $request->getContent();
//$user = json_decode($user,true);
$axios = Apiato::call('User#GetAllUsersAction', [$request]);
return $axios;
}
i expect something like this upon i click number page : [1],2,3,4,5,...,24,25 --> 1,2,...,[6],7,8,9,...25

extracting values from rows to use in a URL

I have generated a data table using the Datatables jquery plugin. The table is populated with JSON.
I want to extract cell values when I make a selection to use in a URL but I can't get it to work.
#I'm using django
import json
#my list
users = [[1,26,'John','Smith'],[2,33,'Dave','Johnson'],[1,22,'Aaron','Jones']]
#my json
user_json = json.dumps(users)
<table class="table table-striped- table-bordered table-hover table-checkable" id="user-table">
<thead>
<tr>
<th>Age</th>
<th>Record ID</th>
<th>First Name</th>
<th>Last Name</th>
<th>Actions</th>
</tr>
</thead>
</table>
<script type="text/javascript">
var userData = {{user_json|safe}};
</script>
var SourceHtml = function() {
var dataJSONArray = userData;
var initTable1 = function() {
var table = $('#user-table');
// begin table
table.DataTable({
responsive: true,
data: dataJSONArray,
columnDefs: [
{
targets: -1,
title: 'Actions',
orderable: false,
render: function(data, type, full, meta) {
//this is where I need help. I need for each a-tag to link to a django url pattern such as href="{% url 'users:select-user' id=id_value %}"
return '<i class="la la-edit"></i>';
},
},
],
});
};
return {
//main function to initiate the module
init: function() {
initTable1();
}
};
}();
jQuery(document).ready(function() {
SourceHtml.init();
});
I need a href link to a django url pattern such as href="{% url 'users:select-user' id=id_value %}" in each a tag. however, I can't get the values from the cells.
Datatables columns.render option can be used to access full data source of current row.
By using columns.render as function type, we can use third (3)
parameter to access another column index form same row of data
source.
var userData = [[1,26,'John','Smith'],[2,33,'Dave','Johnson'],[1,22,'Aaron','Jones']];
$('#example').dataTable( {
"columnDefs": [ {
"targets": -1,
"data": null,
"title": 'Actions',
"render": function ( data, type, row, meta ) {
return 'Download';
}
} ]
} );

How to generate a table dynamically and group rows

I want to generate data in data table based on JSON response. Following is my JSON response:
{
"alertItems": [
{
"id": "PROD-115388",
"errors": [
"Original Estimate is null",
"id is null"
],
"warnings": [
"Original Estimate is above threshold",
"Story points are above threshold",
"These sub tasks are not defined."
]
},
{
"id": "PROD-112479",
"errors": [],
"warnings": [
"Original Estimate is above threshold",
"Story points are above threshold",
"Estimate is missing for these sub tasks : PROD-112329"
]
},
{
"id": "PROD-108461",
"errors": [],
"warnings": [
"Original Estimate is above threshold",
"Story points are above threshold",
"These sub tasks are not defined : Test Case, BA Documentation Task, QA Design and Execute Task, BA/QA/Dev, BA Testing Task, QA Documentation Task, Elaboration"
]
}
],
"numberOfErrors": 0,
"numberOfWarnings": 10
}
I want to generate Table like following:
I have array of warnings and errors. I want to generate a row for each warning/error against its Id. How can I do that in jQuery datatables?
You may use ajax.dataSrc option to specify callback function that will transform your data to desired format:
const transform = data =>
data.alertItems
.map(({id, errors, warnings}) =>
[...errors.map(error => ({id, type: 'error', reason: error})),
...warnings.map(warning => ({id, type: 'warning', reason:warning}))])
.flat();
In order to group your table rows by matching id's in the first column, you may use rowspan HTML attribute set from within drawCallback function (in order to do that, you'll need to ensure that your table rows sorting order is fixed, so that items with the same id will go sequentially regardless of the sorting/filtering).
So, the complete example (with ajax part commented out, since it's not available within live snippet) might look, like:
//original JSON
const srcJSON = {"alertItems":[{"id":"PROD-115388","errors":["Original Estimate is null","id is null"],"warnings":["Original Estimate is above threshold","Story points are above threshold","These sub tasks are not defined"]},{"id":"PROD-112479","errors":[],"warnings":["OriginalEstimateisabovethreshold","Storypointsareabovethreshold","Estimateismissingforthesesubtasks: PROD-112329"]},{"id":"PROD-108461","errors":[],"warnings":["OriginalEstimateisabovethreshold","Storypointsareabovethreshold","Thesesubtasksarenotdefined: TestCase, BADocumentationTask, QADesignandExecuteTask, BA/QA/Dev, BATestingTask, QADocumentationTask, Elaboration"]}],"numberOfErrors":0,"numberOfWarnings":10};
//proper JSON
const transform = data => data.alertItems.map(({id, errors, warnings}) => [...errors.map(error => ({id, type: 'error', reason: error})),...warnings.map(warning => ({id, type: 'warning', reason:warning}))]).flat();
//datatables init
$('table').DataTable({
/*
ajax: {
url: //url to API endpoint returning original JSON
method: //http method (GET, POST, etc)
dataSrc: transform(data)
}
*/
data: transform(srcJSON), //this one should be dropped once ajax section uncommented
paging: false,
orderFixed: [0,'asc'],
columns: [
{data: 'id', title: 'Story Id'},
{data: 'type', title: 'Type'},
{data: 'reason', title: 'Warning Reason'}
],
//group by first col, using rowspan attribute
drawCallback: function(){
//clean up the view
$('tbody td').attr('rowspan',1).show();
//grab datatable into variable
const table = this.api();
//grab visible, sorted table rows
const rows = table.rows({search:'applied',order:'current'}).nodes();
var groupIdTd = null;
//run through the table rows and set 'rowspan' attribute for matching id's
$.each(rows, function(idx){
const rowspan = Number($(groupIdTd).attr('rowspan') || 1);
idx > 0 && table.cell(groupIdTd).data() == table.cell(this,0).data() ?
($(groupIdTd).attr('rowspan', rowspan+1), $(table.cell(this,0).node()).hide()) :
(groupIdTd = table.cell(this,0).node(), $(groupIdTd).attr('rowspan',1));
});
}
})
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/v/dt/jq-3.3.1/dt-1.10.18/rg-1.1.0/datatables.min.css" />
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/rowgroup/1.1.0/css/rowGroup.dataTables.min.css" />
<script type="application/javascript" src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="https://cdn.datatables.net/v/dt/jq-3.3.1/dt-1.10.18/rg-1.1.0/datatables.min.js"></script>
<script type="application/javascript" src="https://cdn.datatables.net/rowgroup/1.1.0/js/dataTables.rowGroup.min.js"></script>
<script src="test.js"></script>
</head>
<body>
<table></table>
</body>
</html>
Solution is to transform the data before passing it to DataTables using ajax.dataSrc option. Another component of the solution is third-party rowsGroup extension which allows to group rows with identical data.
var table = $('#example').DataTable({
'ajax': {
'url': 'https://api.myjson.com/bins/1b72lv',
'dataSrc': function ( data ) {
var resultData = [];
if(data.hasOwnProperty('alertItems')){
$.each(data.alertItems, function( index, record ) {
$.each(record.errors, function( index, message ) {
resultData.push([ record['id'], 'Error', message ]);
});
$.each(record.warnings, function( index, message ) {
resultData.push([ record['id'], 'Warning', message ]);
});
});
}
return resultData;
}
},
'rowsGroup': [0]
});
See this example for code and demonstration.
See jQuery DataTables: ROWSPAN in table body TBODY for more details on rowsGroup extension.

Core 2 MVC with JQuery Datatables

There is a good example on how to use JQuery Datatables with Core MVC at Using jQuery DataTables Grid With ASP.NET CORE MVC
I download the sample project, made some modifications and it works perfectly.
However, I'm getting an error when I try to integrate this into my project.
DataTables warning: table id=example - Requested unknown parameter 'IdStudent' for row 0, column 0. For more information about this error, please see http://datatables.net/tn/4
After I click ok on the error, the table generates with the correct number of rows, but with no data:
This is my class:
public class GridStudent
{
[Key]
public int IdStudent { get; set; }
public string Name { get; set; }
public string LastName { get; set; }
}
The HTML and JavaScript:
<div class="container">
<br />
<div style="width:90%; margin:0 auto;">
<table id="example" class="table table-striped table-bordered dt-responsive nowrap" width="100%" cellspacing="0">
<thead>
<tr>
<th>IdStudent</th>
<th>Name</th>
<th>LastName</th>
<th>Edit</th>
<th>Delete</th>
</tr>
</thead>
</table>
</div>
</div>
<script>
$(document).ready(function ()
{
$("#example").DataTable({
"processing": true, // for show progress bar
"serverSide": true, // for process server side
"filter": true, // this is for disable filter (search box)
"orderMulti": false, // for disable multiple column at once
"ajax": {
"url": "/StudentGrid/LoadData",
"type": "POST",
"datatype": "json"
},
"columnDefs":
[
{
"targets": [0],
"visible": false,
"searchable": false,
}
],
"columns": [
{ "data": "IdStudent", "name": "IdStudent", "autoWidth": true },
{ "data": "Name", "name": "Name", "autoWidth": true },
{ "data": "LastName", "name": "LastName", "autoWidth": true },
{
"render": function (data, type, full, meta)
{ return '<a class="btn btn-info" href="/StudentGrid/Edit/' + full.IdStudent + '">Edit</a>'; }
}
,
{
data: null, render: function (data, type, row)
{
return "<a href='#' class='btn btn-danger' onclick=DeleteData('" + row.IdStudent + "'); >Delete</a>";
}
},
]
});
});
function DeleteData(CustomerID)
{
if (confirm("Are you sure you want to delete ...?"))
{
Delete(CustomerID);
}
else
{
return false;
}
}
function Delete(CustomerID)
{
var url = '#Url.Content("~/")' + "StudentGrid/Delete";
$.post(url, { ID: CustomerID }, function (data)
{
if (data)
{
oTable = $('#example').DataTable();
oTable.draw();
}
else
{
alert("Something Went Wrong!");
}
});
}
</script>
This is the line of code, from the controller, than returns the data:
return await Task.Run(() => Json(new { draw = draw, recordsFiltered = recordsTotal, recordsTotal = recordsTotal, data = data }));
As you can see from the image, the controller is returning the data correctly, but for some reason DataTables can't read it.
I cross check with the sample a thousand times and I can't see a difference on the format of the data being return.
Any suggestions?
This is most likely due to the casing of the serialized JSON. Your data properties in the column definitions within your JavaScript expect Pascal casing. At present, I expect your are serializing JSON as lower camel case rather than Pascal case (e.g. idStudent instead of IdStudent).
To serialize JSON as Pascal case, make sure you have the following in the ConfigureServices method in your Startup class:
services
.AddMvc()
.AddJsonOptions(options =>
{
options.SerializerSettings.ContractResolver
= new Newtonsoft.Json.Serialization.DefaultContractResolver();
});

Categories

Resources