jQWidgets Forums
jQuery UI Widgets › Forums › Grid › jqxGrid + Knockout + mapping : performance
Tagged: jqxGrid; Knockout; mapping
This topic contains 5 replies, has 3 voices, and was last updated by jgaris 11 years, 11 months ago.
-
Author
-
Hi,
We are trying to use jqxGrid with Knockout.
So we started with example given at this address : http://www.jqwidgets.com/jquery-widgets-demo/demos/jqxknockout/index.htm#demos/jqxknockout/grid.htm
Then we add Knockout mapping.
This is the code :
<!DOCTYPE html><html lang="en"> <head> <title id='Description'>This example shows how to integrate jqxGrid with Knockout.js.</title> <link rel="stylesheet" href="http://www.jqwidgets.com/jquery-widgets-demo/jqwidgets/styles/jqx.base.css" type="text/css" /> <script type="text/javascript" src="http://www.jqwidgets.com/jquery-widgets-demo/scripts/jquery-1.10.1.min.js"></script> <script type="text/javascript" src="http://www.jqwidgets.com/jquery-widgets-demo/scripts/json2.js"></script> <script type="text/javascript" src="http://www.jqwidgets.com/jquery-widgets-demo/scripts/knockout-2.2.1.js"></script> <script type="text/javascript" src="http://www.jqwidgets.com/jquery-widgets-demo/jqwidgets/jqxcore.js"></script> <script type="text/javascript" src="http://www.jqwidgets.com/jquery-widgets-demo/jqwidgets/jqxdata.js"></script> <script type="text/javascript" src="http://www.jqwidgets.com/jquery-widgets-demo/jqwidgets/jqxbuttons.js"></script> <script type="text/javascript" src="http://www.jqwidgets.com/jquery-widgets-demo/jqwidgets/jqxscrollbar.js"></script> <script type="text/javascript" src="http://www.jqwidgets.com/jquery-widgets-demo/jqwidgets/jqxmenu.js"></script> <script type="text/javascript" src="http://www.jqwidgets.com/jquery-widgets-demo/jqwidgets/jqxgrid.js"></script> <script type="text/javascript" src="http://www.jqwidgets.com/jquery-widgets-demo/jqwidgets/jqxgrid.selection.js"></script> <script type="text/javascript" src="http://www.jqwidgets.com/jquery-widgets-demo/jqwidgets/jqxgrid.edit.js"></script> <script type="text/javascript" src="http://www.jqwidgets.com/jquery-widgets-demo/jqwidgets/jqxknockout.js"></script> <script type="text/javascript" src="http://www.jqwidgets.com/jquery-widgets-demo/jqwidgets/jqxcheckbox.js"></script> <script type="text/javascript" src="http://www.jqwidgets.com/jquery-widgets-demo/scripts/gettheme.js"></script> <script type="text/javascript" src="knockout.mapping-latest.js" ></script> <script type="text/javascript"> var selectAll = false; $(document).ready(function () { var initialData = []; // Filling initialData with 100 objects for (var i = 1; i <= 100; i++) { initialData[initialData.length] = { id: i, selected : false, firstName: "First name..." + i, lastName: "Last name..." + i, surname: "Surname..." + i}; } // Model declaration var GridModel = function () { this.items = initialData; } // Making observable each property inside model var viewModel = ko.mapping.fromJS(new GridModel()); // Applying model to the page ko.applyBindings(viewModel); // Click handler on updateSelected button $("#updateSelected").click(function () { // selectAll inversion selectAll = !selectAll; // Display text $("#currentId").text("Start"); // Update 'selected' property inside each row $.each(viewModel.items(), function (i, row) { //setTimeout(function () { //console.log("id:" + row.id()); $("#currentId").text(i); row.selected(selectAll); //}, 100 + i); }); // Display text $("#currentId").text("Finish"); }); }); </script> </head> <body class='default'> <input type="button" id="updateSelected" value="update 'Selected'" /> Current updated id : <span id="currentId"></span> <div data-bind="jqxGrid: { height: 400, width: 530, source : items, editable: true, selectionmode: 'singlecell', columns: [ { text: 'id', dataField: 'id', width: 25 }, { text: 'Selected', dataField: 'selected', width: 100 }, { text: 'First name', dataField: 'firstName', width: 125 }, { text: 'Last name', dataField: 'lastName', width: 125 }, { text: 'Surname', dataField: 'surname', width: 125 } ] }" id="jqxGrid"></div> </body></html>
There is a column named “Selected”.
A click on the button is only updating one observable property (“selected”) for each line.But, with only 100 lines, it takes 5-10 seconds to update.
Removing the grid make it quite instantaneous.
Do you know what could be the problem using the grid like that ?
Thanks.
Alain.
Hi,
If you manage the bindings through jqxDataAdapter – http://www.jqwidgets.com/jquery-widgets-demo/demos/jqxknockout/griddataadapter.htm?web, you can use the Grid’s and dataAdapter’s beginUpdate and endUpdate methods when you want to make multiple updates. Otherwise, updating 100 properties will be equal to 100 unnecessary refreshes.
Best Regards,
Peter StoevjQWidgets Team
http://www.jqwidgets.com/Hi Peter,
Thanks for your help.
I used the example you have gave me.
Several things have significately improve response time :
– using beginupdate() and endupdate()
– making observable only the items array (not all the properties of each item)
– using dataAdapter an JS to genrate the grid (instead of using “data-bind” inside HTML)So now response time is like that (using “console.time” in JS code) :
– 100 items : 400ms
– 200 items : 1160ms
– 300 items : 2500ms
– 400 items : 4300msThis is exponential and in term of end-user experience this doesn’t looks good.
So do you know a way to accelerate update and refresh ?
Below the code I used to test performance (based on provided example).
Regards.
Alain.
<!DOCTYPE html><html lang="en"><head> <title id='Description'>This example shows how to integrate jqxGrid using jqxDataAdapter with Knockout.js. </title> <link rel="stylesheet" href="http://www.jqwidgets.com/jquery-widgets-demo/jqwidgets/styles/jqx.base.css" type="text/css" /> <script type="text/javascript" src="http://www.jqwidgets.com/jquery-widgets-demo/scripts/jquery-1.10.1.min.js"></script> <script type="text/javascript" src="http://www.jqwidgets.com/jquery-widgets-demo/scripts/json2.js"></script> <script type="text/javascript" src="http://www.jqwidgets.com/jquery-widgets-demo/scripts/knockout-2.2.1.js"></script> <script type="text/javascript" src="http://www.jqwidgets.com/jquery-widgets-demo/jqwidgets/jqxcore.js"></script> <script type="text/javascript" src="http://www.jqwidgets.com/jquery-widgets-demo/jqwidgets/jqxdata.js"></script> <script type="text/javascript" src="http://www.jqwidgets.com/jquery-widgets-demo/jqwidgets/jqxbuttons.js"></script> <script type="text/javascript" src="http://www.jqwidgets.com/jquery-widgets-demo/jqwidgets/jqxscrollbar.js"></script> <script type="text/javascript" src="http://www.jqwidgets.com/jquery-widgets-demo/jqwidgets/jqxmenu.js"></script> <script type="text/javascript" src="http://www.jqwidgets.com/jquery-widgets-demo/jqwidgets/jqxgrid.js"></script> <script type="text/javascript" src="http://www.jqwidgets.com/jquery-widgets-demo/jqwidgets/jqxgrid.selection.js"></script> <script type="text/javascript" src="http://www.jqwidgets.com/jquery-widgets-demo/jqwidgets/jqxgrid.sort.js"></script> <script type="text/javascript" src="http://www.jqwidgets.com/jquery-widgets-demo/jqwidgets/jqxgrid.edit.js"></script> <script type="text/javascript" src="http://www.jqwidgets.com/jquery-widgets-demo/jqwidgets/jqxknockout.js"></script> <script type="text/javascript" src="http://www.jqwidgets.com/jquery-widgets-demo/jqwidgets/jqxcheckbox.js"></script> <script type="text/javascript" src="http://www.jqwidgets.com/jquery-widgets-demo/scripts/gettheme.js"></script> <script type="text/javascript"> $(document).ready(function () { var initialData = []; // Filling initialData with 200 objects for (var i = 1; i <= 200; i++) { initialData[initialData.length] = { id: i, selected : false, name: "Well-Travelled..." + i, sales: 1000 + i, price: 100 + i}; } var GridModel = function (items) { this.items = ko.observableArray(items); this.disabled = ko.observable(false); this.selected = false; this.updateItem = function () { var self = this; self.selected = !self.selected; console.time("start"); $('#jqxGrid').jqxGrid('beginupdate'); // update all items. if (self.items().length) { $.each(self.items(), function (i, oldItem) { oldItem.selected = self.selected; self.items.replace(self.items()[i], oldItem); }); } $('#jqxGrid').jqxGrid('endupdate'); console.timeEnd("start"); }; }; var model = new GridModel(initialData); var source = { localdata: model.items, datatype: 'observablearray' } var dataAdapter = new $.jqx.dataAdapter(source); $("#jqxGrid").jqxGrid({ width : 530, height : 400, theme: getDemoTheme(), source: dataAdapter, sortable: true, editable: true, selectionmode: 'singlecell', columns: [ { text: 'Selected', dataField: 'selected', width: 80 }, { text: 'Id', dataField: 'id', width: 20 }, { text: 'Name', dataField: 'name', width: 200 }, { text: 'Sales', dataField: 'sales', width: 100, cellsalign: 'right' }, { text: 'Price', dataField: 'price', width: 100, cellsformat: 'c2', cellsalign: 'right' } ] }); ko.applyBindings(model); }); </script></head><body class='default'> <div id='jqxWidget'> <div style="margin-bottom: 10px;"> <input id="updateButton" type="button" data-bind="click: updateItem, jqxButton: {theme: getDemoTheme()}" value="Update Item" /> </div> <div data-bind="jqxGrid: {disabled: disabled}" id="jqxGrid"> </div> </div></body></html>
Hi,
You’ve missed to add dataAdapter.beginUpdate and dataAdapter.endUpdate.
Best Regards,
Peter StoevjQWidgets Team
http://www.jqwidgets.comHi Peter,
Thats right. Sorry for my mistake.
So now performance are :
– 100 items : 210ms
– 200 items : 490ms
– 300 items : 920ms
– 400 items : 1550ms
– 500 items : 2200msI suppose it will not be possible to do better for now. Right ?
This means we need to put busy indicator while doing things like that.
Bad news is that the busy indicator could freezed during update…..Regards.
Alain.
I’m trying to understand how better to use the beginUpdate and endUpdate. In the example above where would you put the dataAdapter.beginUpdate and dataAdapter.endUpdate?
-
AuthorPosts
You must be logged in to reply to this topic.