I am using Dgrid OndemandGrid with Jsonrest store.On scrolling,I am taking 40 records from the database.
var grid= new OnDemandGrid({
store: jsonstore,
columns: Layout,
minRowsPerPage : 40,
maxRowsPerPage : 40,
loadingMessage: "Loading data...",
noDataMessage: "No results found."
}, "grid");
On first time ,I am getting the response Header as
Content-Range items=0-39/132
.On further scrolling ,the response Header is
Content-Range items=38-78/132 instead of 40-79/132.
Can someone tell me how to get the response as 40-79/132 , 80-119..etc..
Add queryRowsOverlap: 0 to the object you're passing to the grid constructor.
queryRowsOverlap defaults to 1, and is the reason the queries overlap. This property is intended to counteract issues with dojo/store/Observable "dropping" items at page boundaries, though it isn't a perfect solution.
Related
I am new to SAP UI5 development. Currently the table is using "growing" and "growingThreshhold", then users can click more to see data of next page. Since we have thousands of data in that table, it takes user time to click more and more again to load next page data. we try to implement a function, that user can enter the page number then click a button and go to the specific page.
<Table id="genTable" growing="true" growingThreshold="60" fixedLayout="false" selectionChange="onHandleSelectChange"
backgroundDesign="Solid" updateFinished="onHandleGeneratorQueueUpdateFinished">
Expected UI:
I added a bar then UI display is good.
<Bar design="SubHeader">
<contentMiddle>
<Input type="Number" id="pageNumber" width="50px"></Input>
<Button id="goToButton" text="Go to" type="Emphasized" press="onHandleGoTo"></Button>
</contentMiddle>
</Bar>
For the backend logic, I refer to below articles, but still doesn't work.
https://blogs.sap.com/2016/12/14/sapui5-pagination-in-sap.m-table-on-button-click-using-odata-service/
https://sapyard.com/advance-sapui5-19-pagination-in-table-control-with-top-and-skip-query-options/
I tried to use read, the it can get the data back from odata service, but the data can't be refreshed in the table.
oModel.read("/ViewQueueSet", {
urlParameters: {
"$top": top,
"$skip": count
},
filters: [new Filter("RoleCode", FilterOperator.EQ, "G")],
useBatch: true,
success: function (tdata) { //successful Read in the server
var json = new JSONModel();
json.setData(tdata);
that.getView().setModel(json,"sapmodel");
sap.ui.core.BusyIndicator.hide();
},
error: function () {
sap.ui.core.BusyIndicator.hide();
}
});
}
also tried to call bindItems
//that.getView().setModel(json,"sapmodel");
//oTable.setModel(json); //JSON is preferred data format
//oTable.bindItems("/results",that.oGenQueueTemplate);
that.getView().byId("genTable").setModel(json);
that.getView().byId("genTable").bindItems("/results",that.oGenQueueTemplate);
Another approach I tried is to use bindItems, it call send the request to odata service, but it doesn't add the parameter top and skip parameter.
oTable.bindItems({
path: "/ViewQueueSet",
model: "sapmodel",
filters: [new Filter("RoleCode", FilterOperator.EQ, "G")],
template: this.oGenQueueTemplate,
// urlParameters: {
// "$top": top,
// "$skip": count
// },
parameters: {
"$top": top,
"$skip": count
}
});
Anyone has any idea about how to implement this functionality?
before I go into detail, please consider using other controls and/or ux patterns. imagine having thousands or millions of elements in backend and user equests to scroll to page 9292929 => for a responsive table (sap.m.Table) you would need to load all elements up to that page. Maybe filtering or some completely different approach could be tha right one.
The correct way to do this is by getting the listbinding and ask it to load more elements. how to ask the binding, may depend on the type of binding as well.
oTable = ... // get a reference on table
oItemsBinding = oTable.getBinding("items");
oItemsBinding.getLength() // will give you total number of elements
oItemsBinding.isLengthFinal() // will tell you if the length is final
oItemsBinding.getCurrentContexts() // will give you array of all loaded contexts.
now a few words to length and the length being final. If you have a binding implementation that knows the total number of objects (e.g. json - since it loads all elements to client, or OData, if cont is implemented in backend) then getLength will tell you the total number of objects.
if the backend doesnt have the count feature implemented, the length becomes final once you reach the end of the list (backend gives you less elements than you require - e.g. top=10,skip=90 returns 10 elements => length 100, not final; top=10,skip=100 returns 4 elements => length=104 becomes final)
Now, you can have a look at various binding implementations. But be aware that there is a lot to consider (direction of growing - upwards/downwards), at least you dont need to think about filtering/sorting - as this is part of the binding.
There is a nice (private) feature in sap.m.Table (or in sap.m.ListBase, to be more precise), which is called GrowingEnablement. you can use it like this:
// dont forget if _oGrowingDelagate is not undefined or similar
oTable._oGrowingDelegate.requestNewPage()
this will load one more page => you could start from reading the implementation of this method if you want to load several pages in one go.
you could also do a simple trick:
// assume you have 20 elements per page (default)
// and want to get to 7th page (elements 121 - 140)
// ckecks for 7th page exists and 7th page not yet loaded are omitted
oTable.setGrowingThreshold(70) // half of 140, so following load will load second page => 71 to 140
oTable._oGrowingDelegate.requestNewPage() // this will load the second page 71 - 140
// once loading is finished (take care of asynchronity)
oItemsBinding.attachEventOnce("dataReceived", function(oEvent){
// reset the growing threshold to 20
oTable.setGrowingThreshold(20)
// scroll to first element of 7th page (index 120, since count starts from 0)
oTable.scrollToInex(120)
})
I hope you can help me because I'm driving mad about this question.
I'm not experienced with Node, Ajax and DataTables, so this is likely a my fault.
I have an html table linked to Datatables. On load document I send a POST request to get data from an MySQL database. If I popolate DataTable with row.add() method all works fine, but if the table grows I could have some slowdowns with this system, so I would like to link the DataTable table with the database so that the program loads only the records to show. Now problem starts.
In my Node file, if I return sql data like so:
res.json(result);
my DataTable shows all the data, but table hasn't right number of record (below the table shows "Showing 0 to 0 of 0 entries (filtered from NaN total entries)" and, even worst, the table has infinite pages, all displaying the same data (the first 10 records).
If instead I return an ajax:
ret = JSON.stringify({
"draw": req.body.draw,
"recordsTotal": result[0]['COUNT(cf)'],
"recordsFiltered": result[0]['COUNT(cf)'],
"data": dati
});
res.send(ret);
DataTables shows the correct number of records in the info line at bottom of table, but no data is displayed.
In console I show the ret object and it seems all right. I'm no idea what to do now.
I resolved!!! It's incredible after near 2 days of attempts.
In html file I put in DataTables ajax :
[...]
dataSrc: 'dati',
[...]
Then in my Nodejs file:
ret = JSON.stringify({
"draw": req.body.draw,
"recordsTotal": result[0]['COUNT(cf)'],
"recordsFiltered": result[0]['COUNT(cf)'],
"dati": dati
});
res.send(ret);
and all works fine.
Im using the datatables plugin for pagination.
I'm trying to get my server-side pagination working, however to start with, im facing the issue of not been able to display the totalRecords entires in the 'Showing 1 to 15 of 15 entries' text. im using this to display all the records:
var resultsTable = tableEl.dataTable( {
"aaData": tableData,
"aoColumns": tableColumns,
"aaSorting": [[1,'asc']],
// "bServerSide": true,
"processing": true,
"serverSide": true,
"sAjaxDataProp": "api/1.0/accounts",
"bProcessing": true,
"pagingType": "simple_numbers",
"bLengthChange": false,
"bAutoWidth": false,
"bScrollCollapse": true,
"iTotalRecords": 34,
"iTotalDisplayRecords":15,
"iDisplayLength": 15
} );
but it still shows me 'Showing 1 to 15 of 15 entries' instead of 'Showing 1 to 15 of 34 entries'. Any idea what im i missing here?Thanks, in advance!
My understanding is that iTotalRecords and iTotalDisplayRecords are values that are returned from the server, not values that you set during initialisation.
Can you add the code that generates the server-side data? How are you actually paging that source data?
In your accounts method, you should be returning a json object that looks something like this:
return Json(new
{
param.sEcho,
iTotalRecords = totalRecords,
iTotalDisplayRecords = totalFilteredRecords,
aaData = result
}, JsonRequestBehavior.AllowGet);
Where iTotalRecords is the total, unfiltered record count and iTotalDisplayRecords is the filtered record count. result contains 15 rows of data because at this point you will have already performed the paging query using the datatable parameters iDisplayStart and iDisplayLength to generate the data. You now have all the information to correctly display the page when you return this json object to the datatable.
I have fixed row numbers to 10 for my subgrids, but if reccount is less than 10 I would want to adjust height subgrid to "auto" or "100%".
So here is my code for this subgrid :
// SUBGRID FOURTH LEVEL
var subgrid_table_id = subgrid_id+"_d",
pager_id = "p_"+subgrid_table_id;
$("#"+subgrid_id).append("<table id='"+subgrid_table_id+"' class='scroll'></table><div id='"+pager_id+"' class='scroll'></div>");
$("#"+subgrid_table_id).jqGrid({
url:"sg31b.php?id="+row_id+"&clt="+clt,
datatype: "json",
idPrefix:"sgd_",
colNames: ['Id','Article','Désignation','Marque','Equivalence'],
colModel: [
{name:'e.id',index:'e.id',hidden:true},
{name:'a.code',index:'a.code', width:100},
{name:'a.descr',index:'a.descr', width:450},
{name:'k.code',index:'k.code', width:80},
{name:'e.equiv',index:'e.equiv',width:100}
],
pager: pager_id,
sortname: 'a.code',
hiddengrid:true,
scroll:true,
height:230,
rowNum:10,
autowidth:true,
caption:'4 - EQUIVALENCE ARTICLES',
gridComplete:function(){
sortDataCol(this);
if($("#"+subgrid_id+"_d").jqGrid('getGridParam','records') < $("#"+subgrid_id+"_d").jqGrid('getGridParam','rowNum')){
$("#"+subgrid_id+"_d").jqGrid('setGridHeight','100%');
}else{
$("#"+subgrid_id+"_d").jqGrid('setGridParam',[{npage:1}]).jqGrid('setGridHeight',230);
}
}
});
$("#"+subgrid_table_id).jqGrid('navGrid',"#"+pager_id,{search:false,add:false,edit:false,del:false});
$("#"+subgrid_table_id).jqGrid('filterToolbar',{stringResult: true,searchOnEnter : false});
fullInputCss();
and the snapshot of result for less than 10 filtered rows :
Now if I press Backspace in search field to obtain more rows, it seems that search doesn't fire because Firebug doesn't show any trace of request :
If I delete added 'setGridHeight' lines in gridcomplete, all runs fine !
I think that one more time I'm wrong in my coding and understanding how jqGrid runs.
Please could someone give me some way to solve this trouble ?
Many thanks in advance. Have a nice day. JiheL
I suppose that the origin of the problem could be id duplicates on your page. Just now I wrote the answer on another your question where I described the problem detailed.
Current implementation of jqGrid (version 4.4.5) has problem in the code of filterToolbar which constructs id for input fields of the filter toolbar based on the following rule:
id="gs_" + cm.name
(see the line of code). It means that the id of the input field for the column a.code will be gs_a.code for every subgrid which you use. So you can have id duplicates.
So I recommend you redesign the naming concept in your code. You can use for example
name: row_id + "a_code", index: "a.code"
In the way the value like "a.code" will be still send during sorting of the grid, but you will have no id duplicates. In some scenarios (is you use repeatitems: false in jsonReader) you could need to use additional jsonmap attribute, but you don't need it in you current code.
I make an ajax request to couchdbwith POST method, giving a list of keys of the docs I want to retrieve.
Everything seems to work fine except the fact that I get 0 rows because the offset is set on the last line.
So it means that:
I'm communicating well with couchdb server (cloudant)
the POST method works
it seems to retrieve the list but just giving it with the offest of last element, i.e. an empty list
Also, trying to order the results differently had no success.
riList var is something like this (from google chrome dev tools):
keys: Array[194]
0: "Wire line diamond core drilling rig"
1: "VUA - isotope geochemistry laboratory"
2: "Volcanologic and Seismological Observatories"
3: "VESOG"
4: "Utrecht University - TecLab, Tectonic Laboratory"
5: "Utrecht University - Experimental and Analytical Laboratories"
.....
which basically is the same of
var riList=["Wire line diamond core drilling rig", "VUA - isotope geochemistry laboratory","Volcanologic and Seismological Observatories","VESOG","Utrecht University - TecLab, Tectonic Laboratory","Utrecht University - Experimental and Analytical Laboratories"];
Here is the code
var riList= ListOfRU.pluck('ri_name');
var queryParams={"keys":riList};
var riResponseList=[];
var ajaxURL= ('_view/'+ self.parentMcDropDownValue);
console.log(ajaxURL, queryParams);
$.ajax({ //retrieve and show on map LABORATORY coordinates
async: true,
url: ajaxURL,
type:"POST",
data:JSON.stringify(queryParams),
dataType: 'json',
timeout:5000,
success:function(response){
console.log("response",response);
riResponseList=response.rows;
},
error:function(){
alert('fetching error');
}
});
chrome developer tools output
response
Object
offset: 194
rows: Array[0]
total_rows: 194
__proto__: Object
as you can see in the output of chrome devtools the offset is 194 so that I have an array with 0 rows because it starts from the last key.
Any idea?
I was tempted to delete this question when I found the bug.
But finally I decided to let it and to explain what was wrong.
If you feel it should be deleted, please motivate this and I'll delete it.
So the answer to my question is very simple: the keys I was retrieving WERE NOT the keys I was selecting with the "keys" parameter.
The error was indeed in the map function where I wrote:
//WRONG ONE!!
function(doc){
if(doc.doctype=='ri'){
emit(doc.ri, doc);
}
}
INSTEAD OF
//RIGHT ONE!!
function(doc){
if(doc.doctype=='ri'){
emit(doc.ri_name, doc);// RI_NAME INSTEAD OF RI!!!!!
}
}
So the lesson is:
When you get an offset which equals the lenght of the array, check if the results are really the one you want to obtain with the map function.