How do I get the showing rows from datatable Scroller extention? - javascript

When using the Scroller extention for datatables, you don't have pagination but all rows in one scrollbar. I would like to know, what event is fired after scrolling down the tables, to e.g. see row 50-60 of 100.. I also need to know how to get that 10 rows out from the datatable. I'am using the lastest versions. Thanks alot.
This is how you get the rows from the current page in Datatable.net without the Scroller extention.
drawCallback: function (settings) {
var api = new $.fn.dataTable.Api(settings);
// Output the data for the visible rows to the browser's console
console.log(api.rows({ page: 'current' }).data().length);
}
Update 1: My Init of Scroller table:
initScrollerTable = function ($table, url, inclFilter, dataTableOptionsSpecific) {
$.ajax({
method: "POST",
url: url,
data: dataParameterHelper.getCommonData(),
dataType: "json"
})
.done(function (rows) {
var dataTableOptions = $.extend(
{},
{ data: rows },
dataTableOptionsSpecific
);
initTable($table, inclFilter, dataTableOptions);
});
};
Update 2 Deeper elaborating on the origional reason for the question to clarify.
Okay long story short. My table contained 26000 rows, and it took 7mins for me to load it. It contained of ALOT of DB calls and the JSON was a size of 21MB! I wanted to optimize it.
First attempt: I tripped my json to absolute minimum bringing it down to 1.5MB but it still took almost 7mins. On the second test it contained all the html, with hardcoded numbers/strings and i did 0 DB calls. It only took 3.5secs!. Yesterday I didn't knew I only had to focus on optimizing my calls to the DB.
Yesterday, when I posted the origional questing, my idea was to populate the table without any data pulled form the DB, and instead load them in a kind of lazy loading way. Let's say I showed the 10 first rows. with 3 column each where I need to call the DB for each cell, that's 30 times total. So the idea was to make 30 request for the (10) current rows, and replace the placeholder with the actually value. If you understand. I would still be better than 26.000 * 3 DB calls :)
And for that I needed to hook up on an event to get the 10 current rows-id's, I could then loop through making the 30 AJAX request. So maybe it's the scroller event I need for that, if there is someone like that.
But I don't know if it's a good idea. Usually a "good" idea is only "good" before/until you learn the best pratice :)
I think I will start focusing on reducing the DB calls with some inner joins and what have you, retrieving a big resultset I can loop through and populate all my 26.000(and later 50.000) rows, in under 15 secs!

SOLUTION
Use xhr event to handle Ajax requests and page.info() to retrieve information about the table as shown below.
Please note that event handler needs to be attached before you initialize your table to handle initial Ajax request.
$('#example').on('xhr.dt', function ( e, settings, json, xhr ) {
var api = new $.fn.dataTable.Api(settings);
var info = api.page.info();
console.log('Data has been loaded', info);
});
DEMO
See this jsFiddle for code and demonstration.

Related

JavaScript - How to loop through every row in every page in a DataTable

How can I loop through every row in each page, not only the first page?
I am using DataTables v1.10.18 and I've managed to loop through the first 10 records, of the first page, but I could never get past the 1st page.
function loopThroughRows() {
var table = $('#table').DataTable();
table.rows().every(function () {
var data = this.data();
});
}
I've looked everywhere, tried many different examples, but it's still not working for me, maybe I'm missing something?
Thanks in advance.
Thanks to #freedomn-m I've found the issue in my case, the controller was bringing only the 10 records for the current page of the table, so the data was loaded page-by-page from the server, therefore it was not available in the UI.

search items that load data from DB in Knockout JS

In my application, I have an observableArray that loads data from DB. This observableArray fills first 25 items from DB and from scrolled down it loads another 25 and it goes on.
Now, I want to implement search, that should display the result searching the whole data from DB and not just from the displayed 25 items.
I tried to get the search result by sending the whole searching text to DB on clicking search button and there is lot of datas in DB which takes much time to load data.
Please let me know how I can get the desired result from DB within ms. Thanks in advance.
To get a well behaving search with Knockout, you should extend your searchText observable that is bound to the input with a rate-limiter
this.searchText = ko.observable('').extend({ rateLimit: { timeout: 500, method: "notifyWhenChangesStop" } })
This will call any subscribers after the input has remained unchanged for 500ms (i.e. when the user stops typing). You could also use the default method notifyAtFixedRate to call the API at least once every X seconds.
And to top it off, a fiddle!
Note: with this being said, if your query is taking 40 seconds, that sounds like a problem with your database query. It's possible that it's taking that long because you're flooding the server with requests, but that still seems awfully slow. This is the strategy we use and it works excellent, but our API response time is <200ms.

Angularjs : not seeing full results from promise unless console is opened

I have a promise that returns some data. I use that data in a data grid (ng-grid, specifically). The grid only displays a small portion of the data unless I open the console at which point it displays all of the data. Why would this happen?
Here is some code:
//This returns a promise with the results of my db query
Admin.getShipments().then(function (data) {
$log.log('data from promise: ', data); <-- this lists 20 elements
$scope.shipments = data;
});
$scope.gridOptions = {
data: 'shipments',
// some column definitions here... removed as not necessary
};
Using the above my grid only displays 6 elements while the console log shows that there are actually 20. If I inspect element (open console) then the grid will suddenly display all 20 elements.
Why? Is the value for $scope.shipments simply not fully populated when the grid goes to retrieve it? If so, how do you work around this?
Here is an attempt at a solution that does not work...
I tried placing the data grid setup inside the promise "then", thinking that this would ensure that I had all of the needed data but the entire grid fails (saying the grid values are undefined) when I do this. Here is an example of that:
//This fails entirely and the grid complains about undefined values
Admin.getShipments().then(function (data) {
$log.log('data from promise: ', data); <-- this lists 20 elements
$scope.shipments = data;
$scope.gridOptions = {
data: 'shipments',
// some column definitions here... removed as not necessary
};
});
How can I reliably get all of my retrieved data to display in this grid without having to open the console to make it appear (and why would simply opening console have such an effect?)
after testing your code, I successfully reproduced this bug, when grid height is missing, by default the grid renders only 20 rows, after adding height, the grid rendered properly.
Example:
js:
$http.get('largeLoad.json').success(function (data) {
$scope.shipments=data;
});
$scope.gridOptions = {
data: 'shipments'
};
});
css:
.gridStyle{
height:500px;
}
Live example: http://plnkr.co/edit/bg6NMW162qKbm6QUlINo?p=preview
This is definitely some sort of bug in ng-grid. I found this value in their code:
// the # of rows we want to add to the top and bottom of the rendered grid rows
var EXCESS_ROWS = 6;
Changing that number changes the number of elements that are displayed. So right now it's 6 and when I load the page I only see 6 records until I open console at which point they all appear. If I set it to 10 I see 10 until I open console and so on. If the number is larger than the available number of records then all records are displayed so a workaround is to simply make the number larger than the number of records you have. Obviously that's a hack but that's all I have time for right now. I'll update if I get around to actually solving the bug.
Actually this sounds like a buffer flush issue. You have a call to print to the console .. I would guess that there isn't a flush to that final call unless the console is open and thus it's blocking the flush to the document.
I would take the call to the console out and see if it works.. if so then research how to force a flush of that buffer.

AJAX progress bar on array iteration?

I am not too familiar with AJAX but I'm sure what I am trying to do is possible.
Basically I have a form with a text area, when the form is submitted the text area is made into an array with each new line being a value. Simple stuff, now my php then performs a database query on each array value. Also simple.
Now as the operation takes a while I want to make it into an AJAX call using jquery, and for every iteration on the array I want it to display the result back on my main page as well as displaying a progress bar.
So if my text area contains a list of 20,000 names and the query is to fetch the ages of these people, the ajax call would split the textarea into an array and iterate the array. For each iteration it should perform the query and send the result to my main page. So on my main page I will see a list that grows over time.
I hope I have explained this well enough, I just need advice on where to start/what to research. Any examples would be greatly appreciated.
Thanks!
As ajax is simply a request for data you cannot create a reliable loading bar easily.
However if you are doing loads of requests as you suggest in your question, "Which by the way is not the best idea".
You could do something like the code below. Again its pretty basic but will give your user a rough idea. I stuck it in a fidddle here for you http://jsfiddle.net/6dgAF/ its a basic example but should give you a jump off point.
function Status(data)
{
this.data = data;
this.size = this.data.length;
this.current = 0;
this.bar = $("#bar");
//Get width of each step of load
this.step = (this.bar.width() / this.size) ;
for(var i =0; i < this.size; i++){
this.getData(this.data[i]);
}
}
Status.prototype.getData = function(string){
//run your ajax here on each string and on success do this
//$.get( "ajax/test.html", function( string ) {
//this.current++;
//this.updateBar();
//});
this.current++;
this.updateBar();
}
Status.prototype.updateBar = function(){
//updates the bar with the current count * step width;
$("span",this.bar).width(this.step*this.current);
}
//Init object and put in dummy data
var status = new Status(new Array("string1","string2","string3","string4","string5","string6","string7","string8","string9","string10"));
An AJAX request is nothing else than requesting data from your server, just like any HTML page. The only difference is that you use Javascript, and don't feed the data to your browser as an HTML page, but use the data some way on your page.
One possible way to do the thing you want is the following:
Set an interval with the refresh rate, which calls a function getData
In getData you perform an AJAX request, which requests a piece of data from the server, which represents the current state. You might want to make sure the server only returns incremental updates, to avoid sending large amounts of data
Use the data on your front page, by displaying it in a friendly way to the user.
The main thing to keep in mind is that the server must save it's current state (the data which it has gathered with its queries), which it must return in the event of an AJAX request.
What you want is called XHR2 - personally I am using dojo
(dojo/request/xhr here)
However it should be possible with jQuery as well, search for jQuery XHR2 progress ...

YUI Datatable - call arbitrary function *once* on sort

We're using a lot of YUI data tables to display data, and rather than using the built-in pagination we've done our own so we can paginate on the server side using AJAX without downloading the whole data set (which is often huge).
Whenever we use the data table's sorting funcionality, though, it will only sort the one page because from YUI's point of view that's the entire data set.
I need to be able to call an arbitrary function to reload the page data whenever the user tries to sort the data. I've looked into DataTable's sortFunction parameter and it's not ideal because it gets called multiple times (once for each row combination it needs) and I need to do it just once.
There are probably plenty of hacky ways I could do this, but what's the "nicest" way of going about this?
Ideally, you would sort on the server side.
when create the datatable, one of the config options is generateRequest (see this example: http://developer.yahoo.com/yui/examples/datatable/dt_bhm.html )
generateRequest is a meant to be a function which generates a URL which returns the correct data set with which to fill the table. You probably have this.
For me, whenever I click on the column header (to sort), it makes a new request to the server, getting the correct page of sorted data.
Why not write a custom function and close over a variable that tracks whether it's been called?
var hasBeenCalled = false;
function mySortFunction(){
if(!hasBeenCalled){
// do something
hasBeenCalled = true;
}
}
Then replace the sortFunction with that.

Categories

Resources