I have a jQuery datatable that is initially populated using ajax call, and when i click anywhere on the table like pagination number or display length dropdown list, the whole page is reloaded indefinetely. Here is how i populate the datatable.
let table = $('#data-table').DataTable();
function populateTable(){
table = $('#data-table').DataTable({
destroy: true,
responsive: true,
serverSide: false,
autoWidth: false,
paging: true,
filter: true,
searching: true,
stateSave: true,
scrollX: true,
lengthMenu: [10, 25, 50, 75, 100],
language: {
"search": "Filtrer: "
},
ajax: {
url: '/Observer/GetActiveClientsByFloor',
type: 'POST',
data: {
FloorId: floorId,
Type: type
},
dataSrc: ''
},
columns: [
{
title: 'Zone',
data: 'LastKnownZone',
},
{
title: 'HiƩrarchie Map',
data: 'MapInfo.mapHierarchyString',
},
{
title: 'Addresse MAC',
data: 'macAddress',
},
{
title: 'SSID',
data: 'ssId',
},
],
createdRow: (row, data, dataIndex, cells) => {
const selectedRowProfileId = $('#selectedRowProfileId', window.parent.document).val();
if (selectedRowProfileId !== '') {
if (data['ProfileId'] === selectedRowProfileId) {
$(row).addClass('selectedCustom');
}
}
},
initComplete: function (settings, json)
{
const response = json;
//Show the respone on other part of the page
}
}).order([[1, 'asc']]).draw(false);
}
I would like to know what could be causing page re-load and also know how to make pagination works.
You don't need to call order([[1, 'asc']]).draw(false) after table initialization, just add
order: [[1, 'asc']]
to your table properties, like this
$(document).ready(function(){
let table = $('#data-table').DataTable({
order: [[1, 'asc']],
//Other properties
});
As you are not using server-side DataTables will make pagination automatically when you click pagination buttons, considering that all data has already been loaded in the first Ajax call, but when serverSide is set to true every time you change the pagination a new Ajax call will be made by datatables sending aditional parameters for pagination, ordering etc and you will need to change you backend query, filters and pagination logic based on that params.
Edit:
Also destroy: true is not needed in your case, as Documentation says:
"Destroy any existing table matching the selector and replace with the new options."
You are not re-creating or replacing your table, so you can just remove it
Related
I have a datatable that gets called in a function like this:
function createDatatable(){
//get table data
var resp = getTableData()
var dataset = resp.data //table data
var total = resp.total //number like 238
//if table already exists
if (myProductGapsTable) {
myProductGapsTable.clear();
myProductGapsTable.rows.add(dataset); //add new dataset
//myProductGapsTable.language.reload(); //trying to get something like this to work
myProductGapsTable.draw();
} else {
//create table
myProductGapsTable = $('#myProductGapsTable').DataTable({
scrollY: "60vh",
scrollX: true,
scrollCollapse: true,
paging: false,
fixedColumns: true,
"autoWidth": true,
data: dataset,
retrieve: false,
"language": {
"emptyTable": "No table data availiable.",
"info": `Showing _START_ to _END_ of ${total} entries`,
},
"sDom": 'ti',
"paging": false,
"preDrawCallback": function (settings) {
pageScrollPos = $("#myProductGapsTableContainer div.dataTables_scrollBody").scrollTop();
},
"drawCallback": function (settings) {
$("#myProductGapsTableContainer div.dataTables_scrollBody").scrollTop(pageScrollPos);
},
buttons: [
{
extend: 'excelHtml5',
text: 'excel',
exportOptions: { rows: { selected: true, search: 'applied' } }
},
{
extend: 'csvHtml5',
text: 'csv',
exportOptions: { rows: { selected: true, search: 'applied' } }
},
],
select: {
style: 'multi',
selector: 'td:first-child',
search: 'applied'
},
order: [1, 'asc'],
});
}
}
I am trying to have the info field use a custom total number for the info footer, this works fine when the table is first created; it will load the number (238 initially) in the footer correctly. But when I call the function again, if the total number is changed (like now lets say total is 77), the footer info text will not show the updated 'out of 77' text that I would like it to have.
I have an if statement that checks if the table has already been created when the function is called, is there any way I can refresh or reload the table's language field? So I can refresh the table's lower dom info text when the if statement is called?
I don't know of a way to do this using the DataTables API, unfortunately, but here is a jQuery/DOM way:
function changeCountTotal() {
total = resp.total;
var info = $('#myProductGapsTable_info').html();
// Format is assumed to be: "Showing 1 to 10 of 1,234 entries"
var regex = /(Showing.*of ).+?( entries)/;
var updatedinfo = info.replace(regex, "$1" + total + "$2");
$('#example_info').html(updatedinfo);
}
This would need to be called after the redraw peformed by myProductGapsTable.draw();, to ensure the other parameters (_START_, _END_) are correctly re-evaluted by DataTables.
If you want to format the total for thousands separators (or whatever is appropriate for your locale), that would be something like this:
total = resp.total.toLocaleString()
(If there is a way to do this using the DataTables API, that would be a better answer, of course.)
I have the following datatable that is set to server side mode:
As you can see on footer, the total of rows is 21.
But, when I call the function that should return the total of rows, it only returns 10, that is the total of the current page:
How to make it returns 21 instead of 10?
Here's the client-side code of the datatable:
tableOcorrenciaAgendadosHoje = $('#tableOcorrenciaAgendadosHoje').DataTable({
ajax: {
url: "/Ocorrencia/GetOcorrencias",
type: "POST",
datatype: "json",
data: function (d) {
d.aba = "agendadosHoje";
}
},
aoColumnDefs: [{
orderable: false, aTargets: [0]
}],
order: [],
columns: colunas,
scrollX: true,
scrollCollapse: true,
fixedColumns: {
leftColumns: 2,
},
language: {
url: "/Content/js/Portuguese-Brasil.json"
},
serverSide: "true",
processing: "true",
});
According to the documentation:
https://datatables.net/reference/api/page.info()
The following should work in your case:
$(table_id).DataTable().page.info().recordsTotal
I found the solution. I simply added the following function to the datatable:
fnDrawCallback: function () {
self.QtdOcorrenciasAgendadosHoje = this.api().page.info().recordsTotal;
}
It always returns the total of records, even when the table is updated.
I have a kendo Grid with no columns definition because grid's fields are dynamics and I don't have any chance to know the fields before databound event.
Example:
var dataSource = new kendo.data.DataSource({
type: "aspnetmvc-ajax",
transport: {
read: {
url: appPath + "Controller/GetGridData",
dataType: "json",
type: "POST",
data: {
dataSourceID: dataSourceId
}
},
},
schema: { data: "data", total: "total"},
pageSize: 10,
serverSorting: true,
serverPaging: true,
serverFiltering: true,
});
$("#grid").kendoGrid({
dataSource: dataSource,
filterable: {
extra: false
},
dataBound: function (data) {
},
pageable: {
pageSizes: true,
pageSizes: [10, 20, 50, 100]
}
)}
Is there a way to modify columns headers dynamically on databound event or after data are loaded but before showing it to users?
I achieved "dynamic" column headers (after many infuriating troubleshooting messages back and forth by Telerik) by requesting the data prior to initialising the grid via an AJAX call then determining the column names based on the data.
$.ajax({
type: "POST",
url: "/Controller/GetGridData",
// *Important* stringify the server-bound object
data: JSON.stringify(dataSourceId),
dataType: "json",
contentType: "application/json",
async: true,
success: function(response) {
// response contains data required for grid datasource
ConstructGrid(response);
}
});
function ConstructGrid(gridData) {
var dataSource = new kendo.data.DataSource({
... attributes
data: gridData,
... more attributes
});
var columnsArray = [];
if(gridData.attributeToCheck = "someValue") {
columnsArray.push({field: attributeEqualToSomeValue, title="attributeMatchingSomeValue"});
}
else {
columnsArray.push({field: attributeNotEqualToSomeValue, title="attributeNotMatchingSomeValue"});
}
.. continue to add more columns based on data then initialise grid
$("#grid").kendoGrid({
dataSource: dataSource,
filterable: {
extra: false
},
columns: columnsArray,
pageable: {
pageSizes: true,
pageSizes: [10, 20, 50, 100]
}
)};
}
Not exactly 100% dynamic but it will change the column names based on the values retrieved from the AJAX call and AFAIK (after chatting back and forth with Telerik), truly dynamic columns are not supported by the grid control.
Check this Jsbin
`https://output.jsbin.com/lesoxes/`
In this example i have used kendo's datasource.
you will get all column details in console.
Might Help You
I am trying to get jsGrid working in a project but I am missing something since I can't make it to work correctly. I have read docs carefully several times.
The scenario is as follow:
An AJAX call for get a list of subregion
An AJAX call for get a list of countries (each time I click on pagination a new request should be made in order to get proper values)
From docs under controller section:
loadData is a function returning an array of data or jQuery promise
that will be resolved with an array of data (when pageLoading is true
instead of object the structure { data: [items], itemsCount: [total
items count] } should be returned). Accepts filter parameter including
current filter options and paging parameters when pageLoading is true.
So my PHP function return data in the "proper" format as expected, meaning:
{
data: [items],
itemsCount: [total items count]
}
I have created a Pastebin with the result I get when the AJAX call is made (for the countries result). I believe the data is right now. So, this is how my code looks like:
$(function () {
$.ajax({
type: "GET",
url: "/adminconsolejsgrid/subregion"
}).done(function (subregion) {
$("#jsGrid").jsGrid({
height: "70%",
width: "100%",
filtering: true,
sorting: true,
paging: true,
autoload: true,
pageSize: 15,
pageButtonCount: 5,
pageLoading: true,
controller: {
loadData: function (filter) {
return $.ajax({
type: "GET",
url: "/adminconsolejsgrid/countries",
data: filter
});
}
},
fields: [
{name: "country_name", title: "Name", type: "text", width: 100, sorting: true},
{name: "country_abbr", title: "Code", type: "text", width: 5, sorting: true},
{
name: "subregion",
title: "SubRegion",
type: "select",
width: 100,
items: subregion,
valueField: "subregion_id",
textField: "subregion_name"
},
{type: "control"}
]
});
});
});
But still not working for me which mean I am not getting any values on the grid. This pic is an example of what I get:
What I am missing? Any help?
This is a follow-up to my earlier question posted here. I have cases where we get large amount of data, around 200KB to be displayed on the jqgrid. In such case, the last sets of data are never displayed. Each record is split by a newline character. The data is in this format:
{"data":{"data":"\tat org.aaa.aaa.aaa.aaa.aaa.aaa(aaa.java:512)[147:org.aaa.aaa.aaa:9.1.1]\n\tat aaa.aaa.aaa.aaa.aaa.aaa(aaa.java:1789)[146:org.aaa:9.1.1]\n"}}
The code for grid is as follows:
$("#grid").jqGrid({
type: "GET",
url: "/getdata",
datatype: "json",
colNames: [''],
colModel: [
{name: 'data', align: 'left', sortable: false}
],
jsonReader: {
root: "data",
cell: "",
id: function () {
return function () {
return $.jgrid.randId();
}
},
page: function() { return 1; },
total: function() { return 1; },
records: function(obj) { return obj.data.length; }
},
loadonce: false,
viewrecords: true,
sortname:'',
rowNum: '9999',
autowidth: true,
ignoreCase: true,
height: "auto",
multiselect: false,
sortable: false,
autoencode: true,
loadComplete: function() {
$("tr.jqgrow:even").css("background", "#DDDDDC");
},
// We will handle the errors with ajax error handlers for now
loadError: function(error){
displayError(error.responseText);
},
beforeProcessing: function (data) {
var items = data.data.split("\n"), i, l, item;
data.logs = [];
for (i = 0, l = items.length; i < l; i++) {
item = $.trim(items[i]);
if (item.length > 0) {
data.data.push([item]);
}
}
}
});
I tried setting the rowNum to '', 99999, nothing worked. The total number of lines wwas The same lines seem to be getting chopped from display in jqgrid. Is there any limit to the amount of data that jqgrid can display? As of now, no pagination has been implemented on jqgrid.
Any pointers are greatly appreciated.
thanks,
Asha
First of all I recommend you to use correct type of all input parameters of jqGrid. In the documentation you will find the table which has "Type" column. The type of rowNum column is integer. So you should use rowNum: 9999 instead of rowNum: '9999'.
Additionally I strictly recommend you always use gridview: true option of jqGrid. In case of placing all data on one page such setting can improve the performance of filling of the grid in many times.
In the same way I don't recommend you to make any modification of the grid inside of loadComplete. It reduce the performance of jqGrid. You can define your custom CSS class for example
.myAltRows: { background: #DDDDDC }
and use the options altRows: true, altclass: "myAltRows". Alternatively you can use rowattr callback to set custom class or custom style on selected rows of the grid. See the answer for more details.
The last remark. I don't recommend you to include options which has default values (for example, type: "GET", loadonce: false, sortname:'', multiselect: false, sortable: false) or properties of colModel having default values (for example align: 'left'). You should examine default values column of the option and colModel options of the documentation.