Vaadin 8 Treegrid always fetching all rows though using AbstractBackEndHierarchicalDataProvider for lazyloading - vaadin8

Hello I am using TreeGrid (Vaadin 8.6.3) with AbstractBackEndHierarchicalDataProvider for lazy loading
I have overridden fetchChildrenFromBackEnd, getChildCount and hasChildren methods.
My total row count in db is 400.
My Issue is whenever the Treegrid is rendered, it is fetching all 400 rows at one show (the offset value is 0 and limit value is 400). I have not overridden the default limit anywhere.
The first call to getChildCount returns 400, fetchChildrenFromBackEnd always has the offset value 0 and limit 400 .

Vaadin said that it's not a bug but a missing features!! ;-(
So, you cannot use treegrid for a large dataset.
https://github.com/vaadin/framework/issues/11447

Related

Displaying data dynamically from SQL database with Golang, JSON, and JavaScript

I have a Golang server that fetches all the rows from a database table.
SELECT * FROM people;
The fetched data is 'marshaled' into JSON:
json.NewEncoder(w).Encode(people)
JavaScript can fetch the rows through its Fetch API.
Now let's say the database table has 10,000 rows but I only want to display as many rows as they fit on the screen.
As I scroll the page I'd like more rows to be fetched dynamically from the database.
Does the client need to send data to the server telling the server to fetch the JSON again with more data?
I would be grateful for any suggestion. Thank you!
Assuming what you're looking for is pagination, then the answer is quite simple, but it requires changes both on the client and the server side:
Getting the data: You'll want the client-side to tell the server how big the batches of data should be (typically 10, 20, 30, 40, or 50 results per call, with a default value of 10).
The second parameter you'll want from the client is to indicate how many results the client has already loaded on their end.
With these two values, you'll be able to enrich the query to include a limit and offset value. The default offset being 0, and default limit being 10.
That means the first query will look something like:
SELECT * FROM people LIMIT 10 OFFSET 0;
This is often shortened to LIMIT 10; or LIMIT 0, 10;.
Now if the client scrolls down, to load the next 10 records, you'll want them to perform an AJAX call providing you the batch size, and the offset value (how many records are already displayed), then just plug in these values, and you'll get:
SELECT * FROM people LIMIT 10 OFFSET 10;
This query tells the DB to skip the first 10 results, and return the next 10.
If you're using actual pages, another common way to handle this is to have the client provide the page size value, and the page number. For example: I want to see 20 people per page, and I want to jump directly from page 1 to page 5, the parameters passed to the server would be something like: page_size=20&page=5
That means that I need a query that skips the first 80 records (20 times 4 pages), a trivial computation:
offset := pageNr * pageSize - pageSize // or (pageNr -1 ) * pageSize
For the query to be:
SELECT * FROM people LIMIT 20 OFFSET 80;
Some general tips:
Avoid SELECT * as much as possible, always be explicit about the fields you select. Adding fields to a table is common, and using select * can result in exposing data you don't want people to see, or your code messing up because it can't handle new fields
Specify the order for your data. Have a created_at field in your table, and sort by that value, or sort by name or whatever. If you don't sort the results in a particular way, how can you guarantee that the first 10 results will always be the same? If you can't guarantee that, why wouldn't it be possible that you're going to skip some records, and display others twice?
Create a People type server-side that represents the records in the DB if you haven't already
It's been quite a number of years since I've done any front-end work, but to know when you need to load more records, you'll want to write some JS that handles the scroll event. There's a number of plugins out there already, and my JS is most likely outdated, but here's an attempt (untested, and to be treated as pseudo-code):
document.querySelector('#person_container').addEventListener('scroll', (function(ls) {
var last = ls[ls.length-1] // last person already loaded
let batchSize = ls.length // IIRC, let is used instead of var now
// returning the actual handler
return function(e) {
// scroll reached bottom of the page
if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight) {
// make AJAX call with batchSize + offset, append new elements after last element
}
};
}(document.querySelectorAll('.person_item')))

JQuery Bootgrid rowCount does not work

Output looks like this----------
Hi,
I am using JQuery bootgrid to display a few hundred records. I am returning a rowCount=10 from server side but its not work and keep showing all the rows.
My source looks like this:
HTML:
<th data-column-id='ItemID' data-type='numeric' data-identifier='true'>ID</th>"+
"<th data-column-id='ItemNumber'>Item Number</th>"+
"<th data-column-id='ItemDescription'>Description</th>"+
"<th data-column-id='ItemStatus'>Status</th>"+
"<th data-column-id='DateReceived'>Received Date</th>"+
"<th data-column-id='ItemNotes' data-formatter='text' data-sortable='false'>Text Description</th>"+
//"<th data-column-id='NoOfItems' data-formatter='select' data-sortable='false'>No. of Items</th>"+
"<th data-column-id='commands' data-formatter='commands' data-sortable='false'>Actions</th>";
Ajax Request:
current "1"
rowCount "10"
searchPhrase ""
Ajax Response:
current 1
rowCount 10
rows [12]
0 Object
1 Object
2 Object
3 Object
4 Object
5 Object
6 Object
7 Object
8 Object
9 Object
10 Object
11 Object
total 12
Any help will be appreciated. Thanks
This confuses many people at first, as it did me.
It's important to remember that pagination is not done by JQ-BG. It's done by the server. JQ-BG only tells the server what page the user is requesting and details like rows per page, search strings, sorted columns, etc. It's up to the server to first filter by the search string (if applicable), sort according to the sorted column, and then do the math about which rows in that result set make up the page that the user is requesting. In the end, the server sends no more than one page's worth of rows. The server also feeds back the total number of pages that are available so that JQ-BG can arrange the tiled page numbers at the bottom for the user to click on.
In the end, this makes sense because no matter the size of the data, it isn't being all sent over the wire in a giant transaction that will, at some point, overwhelm the browser and make the network appear "slow".
But, it does create some challenges, like temporarily storing the filtered, sorted data across ajax requests and doing the pagination within the cached results.

ADF - ViewObject getRowAtRangeIndex returns null even though row count is 300

getRowAtRangeIndex is returning null when I pass in for example 14. However, if I check the rows it says there's 300. I have the ViewObject return all rows automatically. If I run this same method in a click listener, it has no issues. It's only when I'm trying to pre-populate a table. Any ideas?
Thanks, Graeme
I had to do a server event from the client, then it loaded in the correct time. Used this to solve it:
http://killm3-adf.blogspot.com/2014/08/calling-java-method-on-page-load.html
In my case, I was calling this method for a value change listener. The issue was that the Range size was set to 10 and the row I was trying to fetch is 187. Even though the rowCount is greater than the index, range size is less than the index.
Fixed this issue by setting range size as -1 for the corresponding viewobject iterator in the pagedef.

KendoUI filters and paging functionality - How they work with large JSON data

I have 100,000 records right now (will grow in future). I have JSON api call (remote URL, however, within same server) to get those records. If I use KendoUI with paging turned on (say 50 per page), will KendoUI datasource going to fetch all those records and bring them into client and apply paging? Or is it something I need to pass to the server (page size) to be able to only get only needed data for display? If I need to pass, do I have to write custom data source query methods?
Same question goes for using filter input boxes in toolbar within KendoUI.
There are two (efficient) ways of loading that amount of data:
Setting serverPaging to true in the DataSourcedefinition.
Using serverPaging plyst (as #bobosov534 and #gitsitgo suggests) virtual scrolling.
In the both you receive in the server tow parameters: top indicating the number of records to retrieve (what you have defined as pageSize) and skip for the number of records to ignore (no skip means the first top records).
The difference is that int the first you see a pagination bar in the bottom of the grid and in the second you see additional records as you scroll down.
In DataSource.serverPaging you find detailed information on the fields sent to the server for managing pagination.

jQGrid how to correctly turn off paging

So in order to do that i need to remove pager: value in grid declaration and i need to set maximum rows number to rowNum: 100000000,, according with that post How to show all rows in the jqGrid?
But what about json which i need to return from server,
var jsonData = new
{
total = totalPages,
page = page,
records = totalRecords,
rows = ...
}
Which values better to assign to page and totalRecords in that case?
Should i better pass them as zeroes or it is doesn't mater at all in such case?
UPDATE:
I think i would set records to total number rows that will go to jason, and page and total i will set to 1
What do you think? Anymore i can do to correctly turn off jqGrid paging?
It's correct to place page and total to 1 and records to the total number rows. The setting rowNum: 100000000 seems to too large. If you will really post back from the server 100000000 rows of data the user will probably never see the grid. It seems enough to set rowNum to 10000.
If you don't use tree grid you can use local paging of data. In the case you need set just loadonce:true. In the case the server should post all the data to the client and just ignore the input rows parameter. Look at the demo which uses local data paging of 5000 rows of data here and compare the results with the same demo without local data paging here. The difference in the performance will show why I recommend you to use local data paging instead of scrolling the same data in the browser.

Resources