Creating an async event inside a dataTable column and rendering a button according to response
Creating an async event inside a dataTable column and rendering a button according to response
I am using dataTables to represent a list of institutions. One of the columns in the table has button to check API status, so when a user clicks it will say if the API is active or inactive. I have this working but now I will like to make it an async event so when the page or the dataTable is loaded we get the status of the API after few seconds automatically, how can I achieve this as I am unable to find anything useful regarding this. Below is my code.
$.ajax({
url: '/getInstitutionsList',
type: 'GET',
dataType: 'JSON',
success: function(response) {
var institutionsTable = $('#institutionsTable').DataTable({
responsive: true,
data: response.data,
language: dataTableLang,
columns: [
{ data: null, defaultContent: '' },
{ data: 'description' },
{ data: 'email' },
{ data: 'phone' },
{
data: null,
render: function (data, type, row) {
if (locale === 'fr') {
return "<button class=\"btn button-status btn-primary btn-sm ml-4 mb-2\" id= 'checkApiStatus" + data.id_institutions + "' data-instituteid='"+ data.id_institutions +"'> "+ frLocaleDataTable['CHECK API STATUS'] + " <i id='spinner" + data.id_institutions +"' class=\"fa fa-spinner fa-spin hidden\"></i></button>"
} else {
return "<button class=\"btn button-status btn-primary btn-sm ml-4 mb-2\" id= 'checkApiStatus" + data.id_institutions + "' data-instituteid='"+ data.id_institutions +"'>Check API Status<i id='spinner" + data.id_institutions +"' class=\"fa fa-spinner fa-spin hidden\"></i></button>"
}
}
},
{
data: null,
render: function (data, type, row) {
return " <button class=\"button-expire btn-sm ml-4 mb-2\" style=\"border:none;\" data-instituteid='"+ data.id_institutions +"'><i class=\"fa fa-clock\"></i></button>"
}
},
{ data: 'id_institutions' },
{
data: null,
render: function (data, type, row) {
return " <button class=\"button-manage btn-sm ml-4 mb-2\" style=\"border:none;\" data-instituteid='"+ data.id_institutions +"'><i class=\"fa fa-pencil-alt\"></i></button>"
}
},
{
data: null,
render: function (data, type, row) {
return " <button class=\"button-delete btn-sm ml-4 mb-2\" style=\"border:none;\" data-instituteid='"+ data.id_institutions +"'><i class=\"fa fa-trash\"></i></button>"
}
}
],
columnDefs: [
{
targets: [6],
visible: false,
searchable: false
},
{
targets: [0],
checkboxes: {
selectRow: true
}
}
],
select: {
style: 'multi'
},
pageLength: 5,
order: [[ 1, 'asc' ]],
bDestroy: true,
});
}
});
Below is the event on button with button-status class click
$('.button-status').click(function (e){
e.preventDefault();
var instituteId = $(this).data('instituteid');
$('#spinner' + instituteId).removeClass('hidden');
$.ajax({
url: '/getInstitutionStatus/' + instituteId,
type: 'GET',
dataType: 'json',
success: function(response) {
$('#spinner' + instituteId).hide();
document.getElementById('checkApiStatus' + instituteId).classList.remove('btn-primary');
document.getElementById('checkApiStatus' + instituteId).classList.add('btn-success');
document.getElementById('checkApiStatus' + instituteId).innerText = 'Active';
}, error: function (e) {
$('#spinner' + instituteId).hide();
document.getElementById('checkApiStatus' + instituteId).classList.remove('btn-primary');
document.getElementById('checkApiStatus' + instituteId).classList.add('btn-danger');
document.getElementById('checkApiStatus' + instituteId).innerText = 'Inactive';
$("#overlay").fadeOut(2000);
document.getElementById('errorDiv' + instituteId).innerHTML = '<p class="p-3">' + e.message + '</p>';
}
});
});
Here is the screenshot of the dataTable with the buttons for reference
https://i.stack.imgur.com/ZFkig.png
This question has an accepted answers - jump to answer
Answers
Its unclear to me if you are wanting to refresh the whole table periodically or just a particular row. I'll assume the whole table:
One option is to use
ajax
to load the table data instead of the jQuery ajax call you are using. Then use setTimeout() to executeajax.reload()
.Or you can use a jQuery ajax request to refresh the data. Use
clear()
followed byrows.add()
in thesuccess
function. Place this request in a setTimeout() function.Kevin
@kthorngren So no I just want to refresh the API state column, so when the page loads if the API returns a response the button in that row should say active or otherwise inactive
My understanding is the above code works when clicking a button but you want to do this:
Please provide more details of how this will work. Currently you load some data when the Datatable initializes. How are you planning to get the status of the API after a few seconds? Does the status data have an id that can be used to know the row to update? Is the status for all rows or just some?
The
rowCallback
anddrawCallback
callbacks are used to update the Datatables data after initialization. Maybe one of those callbacks will work.Kevin
Maybe you can add the status as part of the row data, it doesn't need to be displayed in a column. In
columns.render
use that status to set the button appropriately. When the status is updated via the API update each row with the status usingrow().data()
orcell().data()
. Then usedraw()
to draw the table which will run thecolumns.render
function.Kevin
@kthorngren So currently, I use the 'id_institutions' from my response which is used to generate the datatable, In my dataTable columns render function, I add this value to html data attribute, so when the user clicks the button, a call is submitted to the API. But this needs to be automatic/async event so when the page is loaded we should get the status automatically. Here is code for the column that renders the button
Click the button and
url: '/getInstitutionStatus/' + instituteId,
is fetched and the status is updated in thesuccess
function, correct?Instead of the button you want to fetch all of the
instituteId
statuses then update the table. Is this correct?Kevin
@kthorngren Yes thats correct, sorry it took so long to explain, English is not my first language
You will use a jQuery ajax() request to fetch the updated status. You can do this in
initComplete
if you want to what until after Datatables initializes. Or you can use some other trigger to send the request.I'm still not sure if the status is part of the row data but I will assume it is. I would use the
success
function to userows().every()
to iterate all the rows. Then userow().data()
orcell().data()
to update the row status. After the loop usedraw()
to update the table display and the status.You can use
rowId
to set the row id to theinstituteId
. In therows().every()
loop you can use -api row().id()
to get the currentinstituteId
to apply the new status.Sorry I'm just providing some vague random ideas that will hopefully help. I still don't understand the details of how you want to fetch the data and what is returned. Hope these ideas give you a start.
Kevin
@kthorngren So status is not part of the row data, only the 'instituteId' is a part. I am fetching the status by clicking the button-status with instituteId data-attribute. So when I click the button I make an ajax API call to /getInstitutionStatus/' + instituteId, If its a success that means the status is active otherwise its inactive
Does this work or is this what you are trying to fix?
Kevin
@kthorngren, yes the button click works with the my code on top. But its not an asynchronous event, so the issue is to fetch the status automatically. So when the page loads the dataTable is created and then after few seconds/minutes the status column values refresh depending on the status being active or inactive, so the user doesn't have to click the button to know the status
Are you planning to use a jQuery ajax() request for this? If so what will be returned?
Kevin
@kthorngren Yes, I think that is the only way I see it. So the response will return an active/inactive status.
Is the response for one
instituteId
? Or will you fetch more than one at a time?What will trigger the ajax request?
Kevin
@kthorngren No the response will be for multiple 'instituteId' and the ajax request should be automatic request after the datatable has loaded, so once the table has loaded it should query the status automatically according to the number of rows and update the status column of each row once it gets the response.
Use
rowId
to set thetr
id to the 'instituteId'. This way you can use therow()
row-selector
as a string-#ID to select the rows.Use
initComplete
to send the ajax request.Loop through the response data. Use the
instituteId
in the response data as therow-selector
to get therow().data()
to update the status.It will be easier to keep the status button updated if you add the status to the row data. It doesn't need to be part of the original data. It can be added after. This way anytime the status changes all you need to do is update the
status
property of the row data.See this example:
http://live.datatables.net/pojofape/1/edit
It uses a button to simulate the ajax request. Move it into -
option initComplete
. Thetable
variable won't be available so you will need to usethis.api()
. For example:Kevin
@kthorngren I am trying your example but I am unable to get the value of 'row.data()' I am getting the value as undefined. here is my sample code
initComplete: function () {
console.log(data);
data.forEach((element) => {
var id_institutions = element.id_institutions;
var api = this.api();
var row = api.row('#' + id_institutions );
console.log(row.data());
});
}
Did you use
rowId
to set the row id?Kevin
@kthorgen It works finally. Thanks for all your help. Here is what I did. to get the status, first I manually added the status in the response.data oject like
response.data.forEach((element) => {
element.status = 'waiting';
});
Then in init complete I fetch the status using ajax