Reputation: 2158
I am trying to bind a ViewModel to a Kendo DataSource which in turn is given to a Kendo Grid. Nothing too fancy at this point.
It sort of works but is VERY slow! I have an alert informing me that I have received my json data (700 rows) within 2 seconds but it then takes around 15 seconds to update the viewmodel.
What am I doing wrong?
Thanks
$(document).ready(function () {
// create the viewmodel we use as the source for the list
var viewModel = kendo.observable({
items: [],
total: function () {
return this.get("items").length;
}
});
var dataSource2 = new kendo.data.DataSource({
data: viewModel,
pageSize: 50
});
// create the grid
$("#grid").kendoGrid({
dataSource: dataSource2,
height: 500,
scrollable: {
virtual: true
},
columns: [
{ field: "ID_ORDER", title: "ID", width: 80 },
{ field: "CREATION_DATE", title: "Creation Date" },
{ field: "STATUS", title: "STATUS", width: 80 },
** more columns (around 10) **
]
});
// pass this on to initialise
APPS.View.Orders.Initialise(viewModel);
});
Then in my typescript I am handling the Initialise call where the viewModel is passed in:
module APP.View.Orders {
export var _Scope: string = "Orders";
var _viewModelOrders: any;
export var Initialise = function (viewModelOrders: any) {
_viewModelOrders = viewModelOrders;
var orderdetails = {
userid: APP.Core.userID,
context: "DEAL"
};
// retrieve all orders
$.getJSON("/api/omsapi/GetOrders", orderdetails, function (mydata) {
try {
alert("item count (1): " + mydata.length);
jQuery.each(mydata, function () {
var newItem = this;
_viewModelOrders.items.push(newItem);
});
alert("item count (2): " + _viewModelOrders.items.length);
}
catch (e) {
alert(e.message);
}
});
}
}
Upvotes: 2
Views: 3260
Reputation: 43728
To explain further, this is due to the line:
_viewModelOrders.items.push(newItem);
Each time you push an item into the array, it triggers a change
event, which the Grid sees and updates itself. So if you push 700 items in, you are really causing the grid to update the DOM 700 times.
It would be much better to aggregate all the items into an array, then assign the array to the DataSource, with something like:
$.getJSON("/api/omsapi/GetOrders", orderdetails, function (mydata) {
datasource2.data(mydata);
Upvotes: 0
Reputation: 2424
You can suspend the observable temporarily by doing the following:
$.getJSON("/api/omsapi/GetOrders", orderdetails, function (mydata) {
try {
var simpleArray = viewModel.items(); // get a reference to the underlying array instance of the observable
jQuery.each(mydata, function () {
items.push(this);
});
viewModel.items.valueHasMutated(); // let the observable know it's underlying data has been updated
}
catch (e) {
alert(e.message);
}
}
Doing the above technique dramatically improves loading times. I have testing this loading a few thousand rows in a reasonable time.
Upvotes: 1
Reputation: 40897
Try building the item array and then assign it into the model.
Something like:
// retrieve all orders
$.getJSON("/api/omsapi/GetOrders", orderdetails, function (mydata) {
try {
alert("item count (1): " + mydata.length);
var items = [];
jQuery.each(mydata, function () {
items.push(this);
});
_viewModelOrders.items = items;
alert("item count (2): " + _viewModelOrders.items.length);
}
catch (e) {
alert(e.message);
}
});
Upvotes: 1