How to reduce data table load time? - ajax

I am working with data table plugin. Initially what I tried is to update the data table plugin from a flat text file. The text file would look like below.
{
"data":[
{
"reference":"#VIP-123",
"application":"Development Aspects",
"applicationType":"Current Application"
},
{
"reference":"#VIP-123",
"application":"Development Aspects",
"applicationType":"Current Application"
}
]
}
I have a HTML file inside this I am writing JavaScript like below.
$(document).ready(function() {
var table=$('#app-table').DataTable( {
"bProcessing": true,
"bPaginate":true,
"bServerSide": false,
"sAjaxSource": "./data/arrays.txt",
"deferRender": true,
"columns": [
{ "data": "reference" },
{ "data": "application" },
{ "data": "applicationType" },
],
"order": [[ 3, "desc" ]],
"ordering": true,
"bFilter": true
} );
The data table is rendering fine until am not having more than 20,000 rows in the table. As the number of rows will increase in the table then data table took more time to load.
What I notices by going through with several site is that we can reduce the load time by using server side processing and for that I need to go with a server which is not possible in my case because I am rendering data from a flat text file. Then I thought to look for static data storage.
So coming to the problem is using indexedDB can we resolve the performance issue and if answer is yes than can anyone let me know how?
I am able to work with indexedDB but unable to integrate with jQuery data table. I mean what I need to make change in the JavaScript. If we can make server side processing with indexedDB then what will be the script?

first read your local file in the following manner:
var rawFile = new XMLHttpRequest();
rawFile.open("GET", file, false);
rawFile.onreadystatechange = function ()
{
if(rawFile.readyState === 4)
{
if(rawFile.status === 200 || rawFile.status == 0)
{
var allText = rawFile.responseText;
}
}
}
Then, use JQuery to parse "allText" into JSON.
Refer this link for parsing into JSON.
Now, create database using "indexedDB API" as mentioned below:
var request = indexedDB.open("<mention_your_db_name_here");
request.onupgradeneeded = function() {
// The database did not previously exist, so create object stores and indexes.
var db = request.result;
var store = db.createObjectStore("books", {keyPath: "reference"});
var titleIndex = store.createIndex("by_reference", "reference", {unique: true});
// Populate with initial data.
store.put({reference: "#VIP-123", application: "Development Aspects", applicationType: "Current Application"});
};
request.onsuccess = function() {
db = request.result;
};
for more details on "indexedDB API", please refer this link

Related

JSViews - failed to load data after setTimeout

I referred to the sample code stated in here and I have amended the following code
data = {items: [
{showItem:true, name:"Johnny Depp2"},
{showItem:false, name:"Henry Best"}
]}
to
data = {},
helpers = {
updateItem: function(ev) {
$.observable(this).setProperty("showItem", !this.showItem);
}
};
setTimeout(function () {
data = {items: [
{showItem:true, name:"Johnny Depp2"},
{showItem:false, name:"Henry Best"}
]}
}, 1000);
but I found the initial data could not be loaded, could anyone teach me how to do this? I am simulating the Ajax page load, thanks very much.

Vue.js Retrieving Remote Data for Options in Select2

I'm working on a project that is using Vue.js and Vue Router as the frontend javascript framework that will need to use a select box of users many places throughout the app. I would like to use select2 for the select box. To try to make my code the cleanest I can, I've implemented a custom filter to format the data the way select2 will accept it, and then I've implemented a custom directive similar to the one found on the Vue.js website.
When the app starts up, it queries the api for the list of users and then stores the list for later use. I can then reference the users list throughout the rest of the application and from any route without querying the backend again. I can successfully retrieve the list of users, pass it through the user list filter to format it the way that select2 wants, and then create a select2 with the list of users set as the options.
But this works only if the route that has the select2 is not the first page to load with the app. For example, if I got to the Home page (without any select2 list of users) and then go to the Users page (with a select2), it works great. But if I go directly to the Users page, the select2 will not have any options. I imagine this is because as Vue is loading up, it sends a GET request back to the server for the list of users and before it gets a response back, it will continues with its async execution and creates the select2 without any options, but then once the list of users comes back from the server, Vue doesn't know how to update the select2 with the list of options.
Here is my question: How can I retrieve the options from an AJAX call (which should be made only once for the entire app, no matter how many times a user select box is shown) and then load them into the select2 even if the one goes directly to the page with the select2 on it?
Thank you in advance! If you notice anything else I should be doing, please tell me as I would like this code to use best practices.
Here is what I have so far:
Simplified app.js
var App = Vue.extend({
ready: function() {
this.fetchUsers();
},
data: function() {
return {
globals: {
users: {
data: []
},
}
};
},
methods: {
fetchUsers: function() {
this.$http.get('./api/v1/users/list', function(data, status, response) {
this.globals.users = data;
});
},
}
});
Sample response from API
{
"data": [
{
"id": 1,
"first_name": "John",
"last_name": "Smith",
"active": 1
},
{
"id": 2,
"first_name": "Emily",
"last_name": "Johnson",
"active": 1
}
]
}
User List Filter
Vue.filter('userList', function (users) {
if (users.length == 0) {
return [];
}
var userList = [
{
text : "Active Users",
children : [
// { id : 0, text : "Item One" }, // example
]
},
{
text : "Inactive Users",
children : []
}
];
$.each( users, function( key, user ) {
var option = { id : user.id, text : user.first_name + ' ' + user.last_name };
if (user.active == 1) {
userList[0].children.push(option);
}
else {
userList[1].children.push(option);
}
});
return userList;
});
Custom Select2 Directive (Similar to this)
Vue.directive('select', {
twoWay: true,
bind: function () {
},
update: function (value) {
var optionsData
// retrive the value of the options attribute
var optionsExpression = this.el.getAttribute('options')
if (optionsExpression) {
// if the value is present, evaluate the dynamic data
// using vm.$eval here so that it supports filters too
optionsData = this.vm.$eval(optionsExpression)
}
var self = this
var select2 = $(this.el)
.select2({
data: optionsData
})
.on('change', function () {
// sync the data to the vm on change.
// `self` is the directive instance
// `this` points to the <select> element
self.set(select2.val());
console.log('emitting "select2-change"');
self.vm.$emit('select2-change');
})
// sync vm data change to select2
$(this.el).val(value).trigger('change')
},
unbind: function () {
// don't forget to teardown listeners and stuff.
$(this.el).off().select2('destroy')
}
})
Sample Implementation of Select2 From Template
<select
multiple="multiple"
style="width: 100%"
v-select="criteria.user_ids"
options="globals.users.data | userList"
>
</select>
I may have found something that works alright, although I'm not sure it's the best way to go about it. Here is my updated code:
Implementation of Select2 From Template
<select
multiple="multiple"
style="width: 100%"
v-select="criteria.reporting_type_ids"
options="globals.types.data | typeList 'reporttoauthorities'"
class="select2-users"
>
</select>
Excerpt from app.js
fetchUsers: function() {
this.$http.get('./api/v1/users/list', function(data, status, response) {
this.globals.users = data;
this.$nextTick(function () {
var optionsData = this.$eval('globals.users.data | userList');
console.log('optionsData', optionsData);
$('.select2-users').select2({
data: optionsData
});
});
});
},
This way works for me, but it still kinda feels hackish. If anybody has any other advice on how to do this, I would greatly appreciate it!
Thanks but I'm working on company legacy project, due to low version of select2, I encountered this issue. And I am not sure about the v-select syntax is from vue standard or not(maybe from the vue-select libaray?). So here's my implementation based on yours. Using input tag instead of select tag, and v-model for v-select. It works like a charm, thanks again #bakerstreetsystems
<input type="text"
multiple="multiple"
style="width: 300px"
v-model="supplier_id"
options="suppliers"
id="select2-suppliers"
>
</input>
<script>
$('#app').ready(function() {
var app = new Vue({
el: "#app",
data: {
supplier_id: '<%= #supplier_id %>', // We are using server rendering(ruby on rails)
suppliers: [],
},
ready: function() {
this.fetchSuppliers();
},
methods: {
fetchSuppliers: function() {
var self = this;
$.ajax({
url: '/admin_sales/suppliers',
method: 'GET',
success: function(res) {
self.suppliers = res.data;
self.$nextTick(function () {
var optionsData = self.suppliers;
$('#select2-suppliers').select2({
placeholder: "Select a supplier",
allowClear: true,
data: optionsData,
});
});
}
});
},
},
});
})
</script>

Datatables ajax authenticated data display username

I'm building a datatable using ajax data which is provides customer data after authentication. Is there a way to pickup the username during authentication and display it on the page to clearly indicate that the table contains the customer's personalised data?
Can I have the username stored in the ajax data file as the "dataSrc".
{
"username": [
[
"item1",
"item2",
"item3"
]
]
}
Then it could be picked up as a variable and then displayed on the page.
var oTable = $('#example').DataTable({
"ajax": {
"url": "data/customerdata.txt",
"type": "POST",
"dataSrc": function(...
},
Thank you in advance for your help!
Something like this should work:
"dataSrc": function (json){
console.log(json.username); // Should output your array e.g. ["item1", "item2","item3"]
$.each(json.username, function(k, v){
console.log(k, v) // Should output each element of your array e.g 0 and item1 then 1 and item2 and then finally 2 and item3
// You can display what you want on the page from this data.
});
return json.data; // returns the data to the table so it can be drawn.
}
Hope that that helps.

Kendo grid data source update approach not working

I have JSON data flowing via Pusher to a simple MVC5 website housing a Kendo Grid. The data, upon arrival, renders successfully in the grid however I'm creating and setting the data source every time. As this seems sinful, I'm trying to determine why my approach to simply updating the data source doesn't render the data.
The grid:
<div id="dashboard"></div>
<script>
$(document).ready(function () {
$("#dashboard").kendoGrid({
columns: [
{ field: "SystemName", width: "50px", title: "System" },
{ field: "Description", width: "100px", title: "Description" },
{ field: "SystemStatus", width: "30px", title: "Status" }
],
height: 600,
scrollable: true,
sortable: true,
});
var dataSource = new kendo.data.DataSource();
var grid = jQuery("#dashboard").data("kendoGrid");
grid.setDataSource(dataSource);
})
</script>
My failed attempt to read in the data without creating and binding a new data source (body of a function call which does happen):
var array = JSON.parse(data.updateGrid);
var grid = jQuery("#dashboard").data("kendoGrid");
grid.dataSource.data = array;
grid.dataSource.read(array);
grid.refresh();
I have confirmed that the data arrives from Pusher correctly yet the above approach does not update the grid.
Thanks in advance for any consideration.
jbt
Use the data() method on the dataSource to set it's data.
var array = JSON.parse(data.updateGrid);
var grid = jQuery("#dashboard").data("kendoGrid");
grid.dataSource.data(array);
You can only set the string value of data on the dataSource if the source is of XML type. Since you are using JSON, you need to call the data function and pass in the new data.
See documentation... http://docs.telerik.com/kendo-ui/api/javascript/data/datasource#methods-data

Create highcharts chart using AJAX/JSON

I am building a website that uses the Highcharts library to display a single line series chart. I am using AJAX to retrieve historical financial data from yahoo finance using their YQL.
The ajax call is working correctly and I can view the returned data in the console for example
console.log( data.query.results.quote[0].Close );
returns the closing price value 457.84
How do I now build the single line series chart using this data?
I cannot find a simple explanation anywhere of how to create the chart using AJAX data.
Thanks
edit: I am fetching the data in AJAX and it works correctly but trying to make the chart work with JSON is where im having difficulties.
This is what my code currently looks like: http://jsfiddle.net/JbGvx/
This is the demo code off the HighStocks website: http://jsfiddle.net/xDhkz/
I think the problem is with the date formatting of the AJAX request. The date is being returned like so 2013-02-25 but the chart wants JS timestamps. Is there a way that I can extract the date from the AJAX, convert it using Date.UTC and then make the chart using the converted data?
If you are considering stock data, consider using HighStocks instead of HighCharts. It can handle many data points much faster than HighCharts is able to.
HighStocks has an example where they pull in AJAX data (1.6 million points) asynchronously here: http://www.highcharts.com/stock/demo/lazy-loading
var chartSeriesData = [];
var chartCategory = [];
$.each(response, function() {
if(this.name!="TOTAL" && this.no!="0")
{
var series_name = this.name;
var series_data = this.no;
var series = [
series_name,
parseFloat(series_data)
];
chartSeriesData.push(series);
}
});
//initialize options for highchart
var options = {
chart: {
plotBackgroundColor: null,
plotBorderWidth: null,
plotShadow: false
},
title: {
text: 'SalesOrder '
},
tooltip: {
pointFormat: '{series.name}: <b>{point.y}</b>'
},
plotOptions: {
pie: {
allowPointSelect: true,
cursor: 'pointer',
center:['60%','60%'],
size:150
,
dataLabels: {
enabled: true,
color: '#000000',
distance: 40,
connectorColor: '#000000',
format: '<b>{point.name}</b>: {point.y} '
}
}
},
series: [{
type: 'pie',
name: 'Browser share',
data:chartSeriesData //load array created from json
}]
}
//options.series[0].setData(datavaluejson);
var chart= $('#container').highcharts(options);

Resources