When scrolling the grid, it does not fire a new request for more items when you reach the end of the 20 items
I am using Dojo version 1.10.4. I created a TrackableRest Store
var TrackableRest = declare([Rest, Trackable]);
var interceptStore = new TrackableRest({
target: 'rest/intercepts/',
accepts: "application/json",
sortParam: 'sort',
rangeStartParam: 'offset',
rangeCountParam: 'limit',
headers:{
'Accept': "application/json",
'Content-Type':"application/json",
'charset':"UTF-8"
},
idProperty: 'id'
});
Then I created a grid:
var grid = window.grid = new CustomGrid({
id: 'grid',
//sort: [{property:'ELNOT'},{property:'RF_AVG'}], // Initialize sort on last name, ascending
collection: interceptsStore,
sort: "id",
getBeforePut: false,
columns: getColumns(),
allowSelectAll: true,
loadingMessage: 'Loading data...',
noDataMessage: 'No results found.',
title: "All",
minRowsPerPage: 20,
maxRowsPerPage: 250
});
The request is sent
http://localhost:8080/OlympiaMap/rest/intercepts/?sort=+id&offset=0&limit=20
And the response includes the header Content-Range with a value of items=0-20/606
and the data looks like
enter image description here
So after two days of waiting I realized that even though you return the Content Header in the desired format it appears that it is using the values in your response total, limit and offset (or whatever you choose for your start and count params). For instance, in my response headers I returned Content-Range with a value of "items 0-20/606" but in the actual response I have a items array with 20 items and a total of 20. When I hard coded this valued (just to test) to match the 606 value I started to see the virtual scrolling work and send request incrementing the start and count. Like this
1st on page load
http://localhost:8080/OlympiaMap/rest/intercepts/?sort=+id&offset=0&limit=20
While scrolling
http://localhost:8080/OlympiaMap/rest/intercepts/?sort=+id&offset=20&limit=20
etc and so on
This is due to a lack of documentation on part of the dstore and dgrid
Related
This is a weird one.
I'm using datatables v1.10.19 with jQuery 3.3.1 and Bootstrap 3.3.7
My datatables grid is configured to display 1000 records (but you can change it to 2500, 5000 and "all").
I've only got about 60 records in my database.
It is using Server-Side processing to retrieve data.
When the grid loads, the pager displays 5 buttons plus an ellipses (as if there is even more).
And even weirder, if I change the drop-down to display "all" records, it acts as I would expect i.e. the pager has 1 page button.
The payloads are pretty much identical:
{
"data": {
"draw": 8,
"recordsTotal": 86,
"recordsFiltered": 66,
"data": [rows of data here]
},
"outcome": {
"opResult": "Success",
"message": ""
}
}
When you click on page 2, it does successfully retrieve a payload with 0 rows.
But there shouldn't be a page 2 available on the pager.
The config object for the datatable looks like this:
eventsSvr.buildConfig = function (url) {
return {
"processing": true,
"serverSide": true,
//"paging": true,
"ajax": {
url: url,
type: ajax.requestPOST,
dataSrc: 'data.data' // the path in the JSON structure to the array which will be the rows.
},
"order": [[1, "asc"]],
"lengthMenu": [[1000, 2500, 5000, -1], [1000, 2500, 5000, "All"]],
"initComplete": function (settings, json) {
eventsSvr.searchTextSpan.text('Search').removeClass('search-is-on');
},
"columns": eventsSvr.grid.columns,
"columnDefs": eventsSvr.grid.columnDefs,
dom: 'ltp'
};
I do have a bunch of custom searches on the page, so I've had to write a lot of code like this:
$.fn.dataTable.ext.search.push(
function (settings, data, dataIndex) {
var picker3 = $(eventsSvr.datePickerInputs[0]).data(icapp.kendoKey);
var picker4 = $(eventsSvr.datePickerInputs[1]).data(icapp.kendoKey);
var rowStartDate = moment(data[3], icapp.date.momentParseFormat).toDate();
var rowEndDate = moment(data[4], icapp.date.momentParseFormat).toDate();
... etc.
}
);
But the odd thing is the different behavior as between "All" records vs 1000 records.
As described above, select "All" records works (resulting in just 1 page button), but none of the other paging sizes work (i.e. 1000, 2500, 5000). The data for the 1 page does return, but I get 5 page buttons and an ellipses.
Any ideas why this would be happening?
When using server-side processing mode DataTables expects draw, recordsTotal and recordsFiltered to be root-level elements. Consider changing your repsonse to the following and you can remove dataSrc option.
{
"draw": 8,
"recordsTotal": 86,
"recordsFiltered": 66,
"data": [rows of data here],
"outcome": {
"opResult": "Success",
"message": ""
}
}
Alternatively you can manipulate the response before passing it to DataTables using function supplied as value for dataSrc option, but I would recommend keep things according to expected format for more readable code.
I'm using a FilteringSelect that use an FilteringSelect as store.
I want to ignore the accented characters that users can enter, and to return all the elements with or without accents. But i don't know what event i have to catch.
Here's my code :
var ccppMemory = new dojo.store.FilteringSelect({
data: centrosPoblado,
idProperty: "id"
});
sboMunicipio = new dijit.form.FilteringSelect({
id: "soMunicipioSelect",
hasDownArrow: false,
placeholder: i18n.tools.searches.ordinary.departmentTown,
store: ccppMemory,
searchAttr: "unitario",
intermediateChanges : true,
queryExpr: "*${0}*",
autoComplete: false,
highlightMatch: "all",
style:"margin-right:5px;width:170px;"
}, "soMunicipioSelect");
sboMunicipio.startup();
To explain better, centrosPoblado is an array that i populate as :
centrosPoblado.push({
id: value.attributes.CODIGO_DANE,
label: value.attributes.NOMBRE_CENTRO_POBLADO,
unitario: value.attributes.DEPTO + " / " + value.attributes.NOMBRE_CENTRO_POBLADO
});
In 'unitario' i have store strings like 'Medellín', ' Bogotá', ....
What i want is that when a user enter medellín, the filterselect ignore and returns 'Medellín' . So what i think i have to do it's to substitute medellin for something like m[eé]d[eé]ll[íi]n, but i don't know where.
Thanks
if anyone is interested, here is the answer :
http://dojo-toolkit.33424.n3.nabble.com/FilteringSelect-avoid-Accented-characters-td4004099.html
You have to overwrite the 'queryEngine' of the Memory that its linked to the FilteringSelect
I want to have client side paging.
But for some reason, I only seem to get back the first page? Even though I know I have two pages worth of data (IE... I step through my code, and I definitely have two...)... What is more baffling is that my links to navigate through the pages never seem to be correct... For instance I would expect the following screen to say 1 of 2...
Also I would expect the bottom right hand side to say View 1-15 of 21?
My feeling is that I am doing something wrong in my data layer to give this pager it's info.
So It only returns the first page.
public static string JsonifyEnc(IEnumerable<TemplateModel> model, int popId, int page, int rows) {
TemplateModel variable = model.ToArray()[0];
ArrayList al = new ArrayList();
//foreach (PatientACOModel patMod in variable.Template) {
int i = 1;
int rowstart = (page * rows + 1) - rows;
int rowend = page * rows;
//Here is where I create the rows... nothing special here
var griddata = new {
total = variable.Template.Count % rows > 0 ? (variable.Template.Count / rows) + 1 : (variable.Template.Count / rows),
page = page,
records = al.Count,
rows = al.ToArray()
};
When I quick wath the total variable it says two?
This would be the first part of my json string that is returned...
{"total":2,"page":1,"records":15,"rows":
So it's there. Also, this is how I am building up my jqGrid...
$(document).ready(function () {
jQuery("#frTable").jqGrid ({
cmTemplate: { sortable: false },
caption: '#TempData["POPNAME"]' + ' Population',
datatype: 'json',
mtype: 'GET',
url: '/Encounters/GetAjaxPagedGridData/', //'Url.Action("GetAjaxPagedGridData", "Encounters", new { popId = TempData["POPULATIONID"] })',//
postData: { popId: '#TempData["POPULATIONID"]'},
pager: '#pager',
jsonReader: {repeatitems: false},
loadonce: true,
height: 'auto',
gridview: true,
viewrecords: true,
rowNum: 15,
shrinkToFit: false,
autowidth: true,
If you use loadonce: true on the client side you should change the server code so that it ignores page and rows options and returns all data. You should just sort the data corresponds to sidx and sord parameter (see sortname and sortorder in jqGrid). You don't need to fill total, page and records parts in the response.
If you use loadonce: true jqGrid load the data and save it in internal data and _index parameters. After that jqGrid change datatype option of jqGrid to "local". So all later sorting, filtering (searching) and paging of data will be done locally.
I have the following in my store. Note the limit is set to 10. I can see on firebug that 10 records are returned. My issue is that my grid pagination doesn't seems to have the correct "page" value.
ie i have 11 records in total ( which should be 2 pages )
proxy:{
type:'ajax',
api:{
read: '/CutterHistory/Read/',
update:'/CutterHistory/Update',
create:'/CutterHistory/Update',
destroy:'/CutterHistory/Remove'
},
reader:{
type:'json',
root:'CutterHistories',
successProperty:'success',
totalProperty:'Total'
},
writer:{
type:'json',
allowSingle:true
},
simpleSortMode: true,
extraParams : {
'sort' : sortBy,
'search' : search,
'limit' : 10,
'destroyed' : destroyed
}
},
and my grid
I'm pretty sure you don't need to include sort and limit as extra params. If you have a paging toolbar, you should simply set the pageSize in your store and the store will take care of all this
May I know if it is possible to put pictures or images into the rows of DataTables (http://datatables.net/) and how does one goes in doing it?
yes, simple way (Jquery Datatable)
<script>
$(document).ready(function () {
$('#example').dataTable({
"processing": true, // control the processing indicator.
"serverSide": true, // recommended to use serverSide when data is more than 10000 rows for performance reasons
"info": true, // control table information display field
"stateSave": true, //restore table state on page reload,
"lengthMenu": [[10, 20, 50, -1], [10, 20, 50, "All"]], // use the first inner array as the page length values and the second inner array as the displayed options
"ajax":{
"url": "#string.Format("{0}://{1}{2}", Request.Url.Scheme, Request.Url.Authority, Url.Content("~"))/Home/AjaxGetJsonData",
"type": "GET"
},
"columns": [
{ "data": "Name", "orderable" : true },
{ "data": "Age", "orderable": false },
{ "data": "DoB", "orderable": true },
{
"render": function (data, type, JsonResultRow, meta) {
return '<img src="Content/Images/'+JsonResultRow.ImageSrcDB+'">';
}
}
],
"order": [[0, "asc"]]
});
});
</script>
[edit: note that the following code and explanation uses a previous DataTables API (1.9 and below?); it translates easily into the current API (in most cases, just ditch the Hungarian notation ("fnRowCallback" just becomes "rowCallback" for example) but I have not done so yet. The backwards compatibility is still in place I believe, but you should look for the newer conventions where possible]
Original reply follows:
What Daniel says is true, but doesn't necessarily say how it's done. And there are many ways. Here are the main ones:
1) The data source (server or otherwise) provides a complete image tag as part of the data set. Don't forget to escape any characters that need escaping for valid JSON
2) The data source provides one or more fields with the information required. For example, a field called "image link" just has the Images/PictureName.png part. Then in fnRowCallback you use this data to create an image tag.
"fnRowCallback": function( nRow, aData, iDisplayIndex, iDisplayIndexFull ) {
var imgLink = aData['imageLink']; // if your JSON is 3D
// var imgLink = aData[4]; // where 4 is the zero-origin column for 2D
var imgTag = '<img src="' + imgLink + '"/>';
$('td:eq(4)', nRow).html(imgTag); // where 4 is the zero-origin visible column in the HTML
return nRow;
}
3) Similar to above, but instead of adding a whole tag, you just update a class that has the image as a background. You would do this for images that are repeated elements rather than one-off or unique pieces of data.
You mean an image inside a column of the table?
Yes, just place an html image tag
like this
<img src="Images/PictureName.png">
instead of putting data (some string) into a column just put the above html tag....
Asp.net core DataTables
The following code retrieve the image from a folder in WWWroot and the path in the DB field ImagePath
{
"data": "ImagePath",
"render": function (data) {
return '<img src="' + data + '" class="avatar" width="50" height="50"/>';
}
}
In case the Name of the picturefile is put together out of one or more informations in the table, like in my case:
src="/images/' + Nummer + Belegnummer + '.jpg"
you can make it that way:
var table = $('#Table').DataTable({
columnDefs: [
{
targets: 0,
render: getImg
}
]
});
function getImg(data, row, full) {
var Nummer = full[1];
var Belegnummer = full[4];
return '<img src="/images/' + Nummer + Belegnummer + '.jpg"/>';}
The picture is in the first column, so Targets = 0 and gets the Information from the same row.
It is necessary to add the parameters data and row.
It is not necessary to outsource it into a seperate function, here getImg, but it makes it easier to debug.