I am working on an ASP.Net Core 2.1 MVC web application and I am using DataTables.Net datatable v1.10.19 for my lists.
I am creating master/detail drill downs where the first list (DataTable) of job activity provides a link on each row to the respective detail record. I am using pagination as well.
On the detail record, I want to have a breadcrumb that takes me back to the job activity list, and to the correct page number where I was at then I clicked on the detail link.
What I am doing is passing the query properties I am using on the Job Activity DataTable as query string parameters to the detail page so I can correctly populate the breadcrumb URL back to the job activity page.
I can see on the DataTable.Net API reference that I can use page.info() from the API to get the current page using something like this;
var table = $('#example').DataTable();
var info = table.page.info();
$('#tableInfo').html(
'Currently showing page '+(info.page+1)+' of '+info.pages+' pages.'
);
The problem is that I initialize the DataTable as part of the table setup and in the body of that function is where I am populating the link data for the detail page. I can't seem to do two .DataTable() calls, such as doing the call to the DataTable function to get the page info to initialize a pageNumber variable and then call the main .DataTable function as it causes the init of the main DataTable function to fail.
So, I need a way to get the current page from within the main .Datatable() function, if possible.
Here is my main DataTable() function;
jQuery(document).ready(function($) {
//Get the Timezone offset between local time and UTC
var d = new Date();
var m = d.getTimezoneOffset();
var minutesToOffset = parseInt(m, 10);
var companyId = $('#company-filter').val();
var siteId = $('#site-filter').val();
var aging = $('#aging-filter').val();
console.log(`companyId: [${companyId}], siteId: [${siteId}], Aging Days: [${aging}]`);
var table = $("#ssflist").DataTable({
//"dom": "lrtip",
"initComplete": function() {
$('#spinner1').hide();
$('#spinner2').hide();
},
"processing": true,
"serverSide": true,
"filter": true,
"orderMulti": false,
"order": [[6, "desc"]],
"ajax": {
"url": `/JobActivity/LoadData?companyId=${companyId}&siteId=${siteId}&agingDays=${aging}`,
"type": "POST",
"datatype": "json"
},
"oLanguage": {
"sSearch": "Filter"
},
"columnDefs": [
{ "orderable": false, "targets": [9, 10] },
{ "className": "text-center", "targets": [0, 9, 10] },
{
"targets": [6, 7],
"render": function(data) {
if (data != null) {
return moment(data).subtract(minutesToOffset, 'minutes').format('M/D/YYYY h:mm a');
}
}
}
],
"columns": [
{
"render": function(data, type, full, meta) {
if (full.ManifestStatus === 0) {
return '<i class="far fa-clock text-primary" title="Not started"></i>';
} else if (full.ManifestStatus === 1) {
return '<i class="fas fa-sync-alt text-primary" title="Pending"></i>';
} else if (full.ManifestStatus === 2) {
return '<i class="far fa-file-alt text-primary" title="Manifested"></i>';
} else if (full.ManifestStatus === 3) {
return '<i class="far fa-times-circle text-danger" title="Failed"></i>';
} else if (full.ManifestStatus === 4) {
return '<i class="far fa-check-circle text-primary" title="Uploaded"></i>';
} else return '<i class="far fa-question-circle text-primary" title="Unknown status"></i>';
},
"name": "ManifestStatus"
},
{
"render": function(data, type, full, meta) {
if (type === 'display' && data != null) {
data =
`<a href="/shippingServicesFileDetail/detail?id=${full.Id
}&returnTitle=Job Activity List&companyId=${companyId}&siteId=${siteId}&agingDays=${
aging}">
<button type="button" class="btn btn-outline-primary btn-sm">` +
data +
`</button></a>`;
}
return data;
},
"data": "Id",
"name": "Id"
},
{ "data": "TransactionId", "name": "TransactionId", "autoWidth": true, "defaultContent": "" },
{ "data": "CompanyName", "name": "CompanyName", "autoWidth": true, "defaultContent": "" },
{ "data": "SiteName", "name": "SiteName", "autoWidth": true, "defaultContent": "" },
{ "data": "ReferenceId", "name": "ReferenceId", "autoWidth": true, "defaultContent": "" },
{ "data": "CreatedDate", "name": "CreatedDate", "autoWidth": true, "defaultContent": "" },
{ "data": "UploadDate", "name": "UploadDate", "autoWidth": true, "defaultContent": "" },
{ "data": "Environment", "name": "Environment", "autoWidth": true, "defaultContent": "" },
{
"render": function(data, type, full, meta) {
data = full.H1RecordCount + full.D1RecordCount + full.C1RecordCount;
return data;
},
"name": "Count"
},
{
"render": function(data, type, full, meta) {
if (full.AzureFileUrl != null) {
data =
`<a href="/JobActivity/getManifest?azureFileUrl=${full.AzureFileUrl
}&azureFileName=${full.AzureFileName}">
<i class="far fa-arrow-alt-circle-down text-primary" title="Download Manifest"></a>`;
return data;
} else {
return null;
}
},
"name": "AzureFileUrl"
}
],
// From StackOverflow http://stackoverflow.com/a/33377633/1988326 - hides pagination if only 1 page
"preDrawCallback":
function(settings) {
var api = new $.fn.dataTable.Api(settings);
var pagination = $(this)
.closest('.dataTables_wrapper')
.find('.dataTables_paginate');
pagination.toggle(api.page.info().pages > 1);
},
});
$('#companyId').on('change',
function() {
table.search(this.text).draw();
});
});
The relevant link code is...
data = `<a href="/shippingServicesFileDetail/detail?id=${full.Id
}&returnTitle=Job Activity
List&companyId=${companyId}&siteId=${siteId}&agingDays=${
aging}">
I want to add a parameter to this link that represents the current page of the Datatable so that I can pass it back in the breadcrumb link on the detail page and have the datatable go to the correct page.
So I need a way to get the current page from within the
var table = $("#ssflist").DataTable({
function itself so I can pass that value in the link to the detail page.
Is there a property or method from within the Datatable function that will get me the current page value?
Related
I am trying to get the <span> tag into the "salesStatusName" column cell that already has some data in it. The tag should be placed in there when the value of the last column "completelyDelivered" is true. However, I also don't want "completelyDelivered" to even be a column in the table, so I assume I somehow need to access the value of "completelyDelivered" attribute in the received JSON.
How it looks now:
https://i.imgur.com/S171i2o.png circle in a separate column
How I want it to look:
https://i.imgur.com/74nCnGu.png circle within Status Name column
I looked around and there are very similar questions, but I was unable to implement any solution.
DataTables instantiation code:
Note that I use AJAX and get JSON code returned
$(document).ready(function () {
$.fn.dataTable.moment('MM-DD-YYYY');
var datatableObj = $('#salesOrdersTable').DataTable({
"ajax": {
"url": "/Orders/GetAll",
"type": "GET",
error: function (error) {
RedirectUserToErrorPage();
}
},
"columns": [
{ "data": "salesOrderNumber" },
{ "data": "salesOrderNumber" },
{ "data": "poNumber" },
{ "data": "orderDateString" },
{ "data": "company" },
{ "data": "salesPerson" },
{ "data": "salesStatusName" },
{ "data": "completelyDelivered" }
],
"columnDefs": [
{
"targets": 0, //salesOrderNumber col
"orderable": false,
"render": function (data) {
return '<input type="button" value="+" onclick="location.href=\'/Shipments/Get?salesOrderNumber=' + data + '\'">';
}
},
{
"targets": 7, //completelyDelivered col
"render": function (data) {
if (String(data) == "true") {
return '<span class="SalesOrderDelivered">⬤</span>';
}
return "";
}
},
{ className: "salesOrderNumber", "targets": 1 },
],
});
I've done some research and figured it out.
Basically, if you write { "data": null }, as a definition for a column, you gain access to all properties of that row. So, in "render": function(data) function, write data["propertyName"] to get the value.
Code:
$(document).ready(function () {
$.fn.dataTable.moment('MM-DD-YYYY');
var datatableObj = $('#salesOrdersTable').DataTable({
"ajax": {
"url": "/Orders/GetAll",
"type": "GET",
error: function (error) {
RedirectUserToErrorPage();
}
},
{"data": "salesOrderNumber",},
{ "data": "salesOrderNumber" },
{ "data": "poNumber" },
{ "data": "orderDateString" },
{ "data": "company" },
{ "data": "salesPerson" },
{ "data": null, },//this is Sales Status column.
//"data: null" accesses all JSON data. We need this so that in "columnDefs" section
//we can use the values of both "completelyDelivered" and "salesStatusName" properties.
],
"columnDefs": [
{
"targets": 0, //button col
"orderable": false,
"render": function (data) {
return '<input type="button" value="+" onclick="location.href=\'/Shipments/GetShipments?salesOrderNumber=' + data + '\'">';
}
},
{
"targets": 6, //Sales Status col.
"render": function (data) { //This is where we can use values of "completelyDelivered" and "salesStatusName" JSON properties.
if (String(data["completelyDelivered"]) == "true") {
return (String(data["salesStatusName"]) + '<span class="AllDelivered"> ⬤</span>');
} else {
return String(data["salesStatusName"]);
}
}
},
{ className: "salesOrderNumber", "targets": 1 },
],
});
I have a DataTable which is doing a GET but i was thinking that protection will be required to help improve UI and can display some sort of error so the user knows if the data is not displayed that an error has occurred and isn't sat watching a black screen.
Any way i know how to do this in a POST but was wondering if there is a way of doing it in a GET.
Current 'Working code
var existingRuleTable = $('#existingRulesDataTable').DataTable({
"ordering": false, // Allows ordering
"searching": false, // Searchbox
"paging": true, // Pagination
"info": false, // Shows 'Showing X of X' information
"pagingType": 'simple_numbers', // Shows Previous, page numbers & next buttons only
"pageLength": 10, // Defaults number of rows to display in table. If changing this value change the show/hide below
"dom": '<"top"f>rt<"bottom"lp><"clear">', // Positions table elements
"lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]], // Sets up the amount of records to display
"fnDrawCallback": function () {
if ($('#dialPlanListTable').DataTable().rows().count() < 11) {
$("div[class='bottom']").hide(); // Hides paginator & dropdown if less than 11 records returned
} else {
$("div[class='bottom']").show(); // Shows paginator & dropdown if 11 or more records are returned
}
},
'ajax': {
"type": 'GET',
"url": "js/dataTable.json",
"data": function (data) {
return data;
}
},
"columns": [ // Display JSON data in table
{ "data": "position" },
{ "data": "startTime" },
{ "data": "endTime" },
{ "data": "selectedDays" },
{ "data": "selectedDates" },
{ "data": "selectedMonths" },
{ "data": "timeRange" },
{
"data": null,
"render": function (data) {
if (buttonclicked == 'Modify') { // Displays the radio button when 'Mod' clicked
return '<label class="c-radio" style="margin-bottom: 0px">'
+ '<input type="radio" name="existingRuleActionRadioButton" value="option1">'
+ '<span class="fa fa-check"></span>'
+ '</label>';
} else if (buttonclicked == 'Delete') { // Displays the delete button when 'Del' clicked
return '<button name="deleteRuleButton" class="btn btn-danger" id="' + data.position + '">'
+ '<i class="fa fa-trash-o" style="font-size: large"></i>'
+ '</button>';
} else {
return ''; // Needed for the 'Add' button click
}
}
}
]
});
Things i have tried
Added this at the end which works BUT i don't know the state (success/error)
"initComplete": function(settings, json) {
alert( 'DataTables has finished its initialisation.' );
}
Then tried the blow AJAX which fires and dropd into the correct 'Success/Error' but this then does not render my DataTable
'ajax': {
"type": 'GET',
"url": "js/dataTable.json",
"data": function (data) {
return data;
},
success: function(data){
alert('Success');
},
error: function(e){
alert('Failed');
}
},
Datatables provides a number of events that can be hooked into:
https://datatables.net/reference/event/
In this case, rather than use initComplete (which seems to be for the DataTables 'Editor' plugin), it looks like the event to hook into is the error event:
https://datatables.net/reference/event/error
You could also look into the draw and xhr events.
It looks like using success: and error: on the ajax: property is overwriting dataTables use of those to render the table; this could be why the xhr event is exposed rather than expose the underlying ajax promise.
I have an ASP.Net Core 2.1 API that serves as the backend data store for my web site. The API endpoints that return a list of records accepts the PageNumber and PageSize parameters and it then returns the specified page of records.
Now, in my ASP.Net 2.1 MVC website, I am trying to use a Datatables.net datatable to present the list of records to the user. I have everything working OK except I can't figure out how to get the page number from the datatable when a user clicks on a page number in the pagination control. In the examples I have looked at, the Controller has a loaddata action and it is retrieving values from the HttpContext.Request.Form but I can't see that there is an actual PageNumber property available.
Here is the javascript that is in my View;
<script>
jQuery(document).ready(function ($) {
var table = $("#companylist").DataTable({
"processing": true,
"serverSide": true,
"filter": true,
"orderMulti": false,
"ajax": {
"url": "/Companies/LoadData",
"type": "POST",
"datatype": "json"
},
"columnDefs": [
{ "orderable": false, "targets": 7 },
{ "className": "text-center", "targets": [6] },
{
"targets": [2],
"createdCell": function(td, cellData, rowData, row, col) {
if (cellData) {
$(td).html('<i class="far fa-check-circle text-primary""></i>');
} else {
$(td).html('<i class="far fa-times-circle text-danger""></i>');
}
}
}
],
"columns": [
{ "data": "Id", "name": "Id", "autoWidth": true },
{ "data": "CompanyName", "name": "CompanyName", "autoWidth": true },
{ "data": "PrimaryContactName", "name": "PrimaryContactName", "autoWidth": true },
{ "data": "PrimaryContactTitle", "name": "PrimaryContactTitle", "autoWidth": true },
{ "data": "PrimaryContactPhone", "name": "PrimaryContactPhone", "autoWidth": true },
{ "data": "PrimaryContactEmail", "name": "PrimaryContactEmail", "autoWidth": true },
{ "data": "IsEnabled", "name": "IsEnabled", "autoWidth": true },
{
"render": function (data, type, full, meta) { return `<i class="far fa-edit text-primary" title="Edit">`; }
}
],
// From StackOverflow http://stackoverflow.com/a/33377633/1988326 - hides pagination if only 1 page
"preDrawCallback": function (settings) {
var api = new $.fn.dataTable.Api(settings);
var pagination = $(this)
.closest('.dataTables_wrapper')
.find('.dataTables_paginate');
pagination.toggle(api.page.info().pages > 1);
}
});
});
And here is my LoadData controller action;
public async Task<IActionResult> LoadData()
{
try
{
await SetCurrentUser();
ViewData["Role"] = _currentRole;
var draw = HttpContext.Request.Form["draw"].FirstOrDefault();
var start = Request.Form["start"].FirstOrDefault();
var length = Request.Form["length"].FirstOrDefault();
var sortColumn = Request.Form["columns[" + Request.Form["order[0][column]"].FirstOrDefault() + "][name]"].FirstOrDefault();
var sortColumnDirection = Request.Form["order[0][dir]"].FirstOrDefault();
var searchValue = Request.Form["search[value]"].FirstOrDefault();
var pageSize = length != null ? Convert.ToInt32(length) : 0;
var request = new CompaniesGetListRequest
{
OrderBy = SetOrderBy(sortColumn, sortColumnDirection),
Filter = SetFilter(searchValue),
PageNumber = ???, //<--- Where do I get tis value?
PageSize = pageSize,
};
var tokenSource = new CancellationTokenSource();
var token = tokenSource.Token;
var companyData = await _client.GetCompanyListAsync(request, "api/companies/filtered", token);
var recordsTotal = companyData.Paging.TotalCount;
var data = companyData.Companies.ToList();
return Json(new
{
draw = draw,
recordsFiltered = companyData.Paging.TotalCount,
recordsTotal = companyData.Paging.TotalCount,
data = companyData.Companies.ToList()
});
}
catch (Exception ex)
{
const string message = "An exception has occurred trying to get the list of Company records.";
_logger.LogError(ex, message);
throw;
}
}
It looks like I only have the Start value, which is the next record number in the list and the length, which is the page size. I need to determine the PageNumber as I do not want to return the entire data set from the backend data store dues to the size of the data set. I just want to grab one page at a time.
This is probably a simple issue but I am just not having any luck finding an answer.
I got this answer from Datatables forum.
var page = Math.ceil(oSettings._iDisplayStart / oSettings._iDisplayLength) + 1;
Hope this helps.
PS: Link to Forum
I have a js data table that I have implemented for pagination of data. It uses the jQuery data table. The data is being displayed correctly. However, I want to add an element within the first row of the data table.
Before I added it like this : <td>#Html.ActionLink(item.CarId, "Detail", "Cars", new { id = item.CarId},null)
<span class="dt-expand-btn js-expand-btn">+</span></td>
What I want to add within the td of the js is : <span class="dt-expand-btn js-expand-btn">+</span>
var carsDataTable = $('.js-cars-lists').DataTable({
"ajax": {
"url": "/Cars/CarsPagination",
"processing": true,
"serverSide": true,
"language": {
"paginate": {
"previous": '<i class="material-icons">chevron_left</i>',
"next": '<i class="material-icons">chevron_right</i>'
}
},
"order": [0, "asc"],
"type": "POST",
"datatype": "json"
},
"columns": [
{
"data": "CarId", "name": "CarId", "autowidth": true,
"render": function (data, type, row, meta) {
$(row.CarId).css('color', 'red');
return '' + row.CarId + '';
}
},
{ "data": "CarName", "name": "CarName", "autowidth": true },
Could someone please help me to achieve this ? Also, paginate icons are not appearing. Please help.
jQuery DataTable has a function of render it accepts 4 parameters function(data, type, row) which you can control the rendering of your rows. You can now check the rows of a table and add your element in it.
You can use columnDefs method and then render:
...
columnDefs: [{
"render": function(data, type) {
return '<span class="dt-expand-btn js-expand-btn">+</span>';
},
"targets": 0
}]
...
targets refers to the index of the table column (since you are referring to the 1st column) set it to 0
I have a variable row['case'] returned from AJAX which is equal to "Hello World!". The problem is that when I try to assign it to another variable, only "Hello" is getting assigned, row['case'] = "Hello", instead of row['case'] = "Hello World!".
Here's the block of code where the issue is present:
$(document).ready(function() {
var table = $('#peacecard').DataTable({
"ajax": "http://localhost:8080/peace_reports/data.php",
"columns": [
{
"className": 'details-control',
"orderable": false,
"data": null,
"defaultContent": ''
},
{ "data": "Name" },
{ "data": "Vendor", "className": 'dt-right' }
{ "data": "case", "render": function(data, type, row, meta){
if (data == "true"){
data = "<i title="+row['case2']+" id='thei'; }
else { data = ""; }
return data; },
"className": 'dt-center'}
],
"order": [[1, 'asc']]
});
This is what console.log(row) shows:
Object {Vendor: "123", Name: "MyHome", case2: "Hello World!"}
You are missing quotes and a </i> on this line:
data = "<i title="+row['case2']+" id='thei';
It should be something like:
data = "<i title='"+row['case2']+"' id='thei'></i>";