Help: iDisplayLength and iDisplayStart are NaN...
Help: iDisplayLength and iDisplayStart are NaN...
I have a data table using Scroller with the following init:
[code]
_dataTable = getTableElement().dataTable({
sDom: '<"top"i<"clear">>rtS<"bottom"i<"clear">>',
sScrollY: '300px',
bDeferRender: true,
bAutoWidth: false,
bProcessing: true,
bServerSide: true,
sAjaxSource: ajaxUrl,
oLanguage: ....,
aoColumns: .....
[/code]
When I get into fnServerData (and on the server), the "iDisplayLength" parameter is "NaN". If I handle this on the server (by defaulting it), the 2nd "page" has "iDisplayStart" = "NaN".
As far as I know, this is never supposed to happen. What am I doing Wrong?
[code]
_dataTable = getTableElement().dataTable({
sDom: '<"top"i<"clear">>rtS<"bottom"i<"clear">>',
sScrollY: '300px',
bDeferRender: true,
bAutoWidth: false,
bProcessing: true,
bServerSide: true,
sAjaxSource: ajaxUrl,
oLanguage: ....,
aoColumns: .....
[/code]
When I get into fnServerData (and on the server), the "iDisplayLength" parameter is "NaN". If I handle this on the server (by defaulting it), the 2nd "page" has "iDisplayStart" = "NaN".
As far as I know, this is never supposed to happen. What am I doing Wrong?
This discussion has been closed.
Replies
T
sEcho = 1
iColumns = 9
sColumns =
iDisplayStart = 0
iDisplayLength = NaN
mDataProp_0 = null
mDataProp_1 = null
mDataProp_2 = null
mDataProp_3 = null
mDataProp_4 = null
mDataProp_5 = null
mDataProp_6 = null
mDataProp_7 = null
mDataProp_8 = null
sSearch =
bRegex = false
sSearch_0 =
bRegex_0 = false
bSearchable_0 = true
sSearch_1 =
bRegex_1 = false
bSearchable_1 = true
sSearch_2 =
bRegex_2 = false
bSearchable_2 = true
sSearch_3 =
bRegex_3 = false
bSearchable_3 = true
sSearch_4 =
bRegex_4 = false
bSearchable_4 = true
sSearch_5 =
bRegex_5 = false
bSearchable_5 = true
sSearch_6 =
bRegex_6 = false
bSearchable_6 = true
sSearch_7 =
bRegex_7 = false
bSearchable_7 = true
sSearch_8 =
bRegex_8 = false
bSearchable_8 = true
iSortingCols = 1
iSortCol_0 = 1
sSortDir_0 = asc
bSortable_0 = false
bSortable_1 = false
bSortable_2 = true
bSortable_3 = true
bSortable_4 = false
bSortable_5 = false
bSortable_6 = false
bSortable_7 = false
bSortable_8 = false
_ = 1310644923367
This reference page describes the JSON object DataTables expects:
http://www.datatables.net/usage/server-side
Here's an example :
[code]
{"sEcho":1
,"iTotalRecords":11
,"iTotalDisplayRecords":10
,"aaData":[
["1","MDH","MDS - API"],["2","P2PS","P2PSClient"]
,["3","RMDS","teswt"],["4","RWDS","test"]
,["4","RWDS","test"],["4","RWDS","test"]
,["4","RWDS","test"],["4","RWDS","test"]
,["4","RWDS","test"],["4","RWDS","test"]
,["4","RWDS","test"]
]}
[/code]
http://www.datatables.net/forums/discussion/2783/json-format/p1
and see http://datatables.net/examples/data_sources/server_side.html for a server side PHP script that returns the correctly formatted JSON.
With Chrome or Firebug's debugging tools in your browser, you can view the JSON that was returned to your page from the server. The easiest way to get there in Chrome is to right click anywhere on your HTML page and choose "inspect element", then go to Network (you may need to refresh your page and have the AJAX call run again) which shows network resources the browser downloaded. Click on your server side script in that list and you can view the outbound and inbound data by selecting different tabs in the main pane in the middle.
Get the server side code running and I think it will fix this.
Here's the full init:
[code]
_dataTable = self.getTableElement().dataTable({
sDom: '<"top"i<"clear">>rtS<"bottom"i<"clear">>',
sScrollY: '300px',
bDeferRender: true, // don't create all the rows at first, only when needed
bAutoWidth: false,
bProcessing: true,
bServerSide: true,
sAjaxSource: ajaxUrl,
oScroller: { trace: true },
oLanguage: {
sLengthMenu: _lengthMenuToUse,
sEmptyTable: 'Your Cart is Empty',
sZeroRecords: 'Your Cart is Empty',
oPaginate: {
sFirst: '',
sLast: '',
sPrevious: '',
sNext: ''
}
},
aoColumns: [
{ // delete column
bSortable: false, sWidth: '5%', mDataProp: null, bUseRendered: false, bVisible: showDelete,
fnRender: function (oObj) { return _deleteItemTemplate.tmpl(oObj.aData).outerHTML(); }
},
{ // image
bSortable: false, sWidth: '5%', mDataProp: null, bUseRendered: false,
fnRender: function (oObj) { return _imageTemplate.tmpl(oObj.aData).outerHTML(); }
},
{ // item num
bSortable: true, sWidth: '13%', mDataProp: null, bUseRendered: false,
fnRender: function (oObj) { return _itemNumberTemplate.tmpl(oObj.aData).outerHTML(); }
},
{// Description
bSortable: true, mDataProp: null, bUseRendered: false,
fnRender: function (oObj) { return _descTemplate.tmpl(oObj.aData).outerHTML(); }
},
{ // Size
bSortable: false, sWidth: '10%', sClass: 'colSize', mDataProp: null, bUseRendered: false,
fnRender: function (oObj) { return _sizeTemplate.tmpl(oObj.aData).outerHTML(); }
},
{ // Min Quantity
bSortable: false, sWidth: '5%', sClass: 'colQty', mDataProp: null, bUseRendered: false, bVisible: showMinQty,
fnRender: function (oObj) { return _minQtyTemplate.tmpl(oObj.aData).outerHTML(); }
},
{ // Quantity
bSortable: false, sWidth: '20%', sClass: 'colQty', mDataProp: null, bUseRendered: false,
fnRender: function (oObj) { return _quantityTemplate.tmpl(oObj.aData).outerHTML(); }
},
{ // Unit Cost
bSortable: false, sClass: 'unitCost', sWidth: '10%', mDataProp: null, bUseRendered: false,
fnRender: function (oObj) { return _unitCostTemplate.tmpl(oObj.aData).outerHTML(); }
},
{ // Total Cost
bSortable: false, sClass: 'totalCost', sWidth: '15%', mDataProp: null, bUseRendered: false,
fnRender: function (oObj) { return _totalCostTemplate.tmpl(oObj.aData).outerHTML(); }
}
],
aaSorting: [[1, 'asc']],
fnServerData: function (sSource, aoData, fnCallback) {
_debug('debug', 'Retrieving Shopping Cart Items');
if (_showZeros == false) {
aoData.push({ name: 'excludeQuantityZero', value: 'true' });
}
$.getJSON(sSource, aoData, function (json) {
if (json.Success == false) {
_debug('error', json.Message);
alert(json.Message);
}
else {
fnCallback(json.Data);
}
});
},
fnRowCallback: function (row, aData, iDisplayIndex, iDisplayIndexFull) {
// grab the quantity box and the remove button
var boxEl = $(row).find('.quantity');
var delEl = $(row).find('.removeCartItemButton');
var box = $(boxEl);
var del = $(delEl);
// grab the key
var itemKey = box.data('itemKey');
// set it on the row
$(row).data('itemKey', itemKey);
// if it's readonly, disable them
if (isReadOnly == true) {
box.attr('disabled', true);
del.attr('disabled', true);
}
else {
// check to see if we have a pending value for this.
var newVal = _getPendingValue(itemKey);
var disable = false;
if (newVal != null && newVal != box.value) {
if (newVal == -1) {
// it's deleting - disable this row
$(row).addClass('disabled');
disable = true;
newVal = 0;
}
$(row).find('.totalCost').html('[Pending]');
box.val(newVal);
}
if (disable == false) {
// wire up up/down and ui events.
box.numericUpDown({
downBefore: (typeof (TouchUtils) != "undefined")
})
.change(function (e) {
var val = box.val();
_onCartItemQuantityChanged(val, Number(itemKey));
e.preventDefault();
});
del.click(function (e) {
self.removeOrderItem(itemKey);
self.redraw(); // cause the above logic to be run to disable the row.
e.preventDefault();
});
}
}
return row;
}
});
[/code]
This is an empty table... then fnServer gets called.
the aoData collection -before- being sent to the server has "NaN" for the "iDisplayLength" parameter. My server code has nothing to do with it!!
Allan
var _defaultLengthMenu = 'Display ' +
'20' +
'50' +
'100' +
'All' +
' items';
var _lengthMenuToUse = _defaultLengthMenu;
[/code]
Would that be bad?
In the end, I can get it to make the JSON call, but without a valid server side script in place, it's not getting anywhere.
Are you familiar with the debugger in Firefox or Chrome?
----------
but back to what I was asking earlier: you ARE pulling from the AJAX JSON on the first draw, whether you know it or not. That's the only way you have data to begin with, given your code.
Can you post your server side script? If it's not paginating/scrolling properly, it may be an issue on the server side.
Also, I know you are using localhost at the moment, but is there any way you can put it up on the web so I can see it in action? I'm not sure I'll be able to figure it out without being able to reproduce or see it myself.
Allan
Thanks
Allan
You can see the issue this causes by running:
[code]
$('#shoppingCartItemsTable').dataTable().fnSettings().oScroller.s.rowHeight
[/code]
the value is 0 - which shouldn't be the case of course, but since you have the element hidden, there can't be a hight calculated (this is the function in question: https://github.com/DataTables/Scroller/blob/master/media/js/Scroller.js#L525 ).
So the fix is to not make the element hidden :-). Another option would be to set the row height manually: http://datatables.net/docs/Scroller/1.0.0/_anonymous__Scroller.oDefaults.html#rowHeight_details .
Allan
Can I add the Scroller stuff after it renders?
One more question about it... Can I set sScrollY to something that will make it take up all the space given to it, or at least a number of rows? hard-coding the size in pixels is a bit of a problem.
[quote]tommck said: Can I set sScrollY to something that will make it take up all the space given to it[/quote]
You can give it a relative size such as 100%, but I would imagine the best way to do it would be to control the size of the scrolling element using Javascript. That way you can calculate the height of the window (minus the header, or whatever you want) and then set the size to that.
Allan