<!DOCTYPE HTML><html> <head> <meta charset="UTF-8"> <title>My Mobile App</title> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=0"> <!-- <link rel="shortcut icon" href="images/favicon.png"> <link rel="apple-touch-icon" href="images/apple-touch-icon.png"> --> <!-- CSS --> <link rel="stylesheet" href="css/main.css"> <link href="js/libs/kendoui/styles/kendo.mobile.all.min.css" rel="stylesheet" /> <!-- jQuery --> <!-- Using the jQuery in Kendo UI --> <script src="js/libs/kendoui/js/jquery.min.js"></script> <!-- Angular JS --> <script src="js/libs/angular/1.3/angular.min.js"></script><!-- <script src="js/libs/angular/1.3/angular-route.min.js"></script> --> <!-- Kendo UI --> <script src="js/libs/kendoui/js/kendo.all.min.js"></script> <!-- application scripts --> <script src="js/app.js"></script> <!-- Controllers --> <script src="js/controllers/controllers.js"></script> <script src="js/controllers/accounts.js"></script> <script src="js/controllers/metrics.js"></script> </head> <body style="display:none;" kendo-mobile-application k-hash-bang="true" ng-app="myApp"> <!--application UI goes here--> <!-- Accounts --> <kendo-mobile-view id="accounts" k-title="'Customer Accounts'" k-layout="'default'" ng-controller="AccountsController"> <kendo-mobile-list-view id="accountslist" class="item-list" k-template="templates.accountsTemplate" k-data-source="myAccounts.accountsDataSource"> </kendo-mobile-list-view> </kendo-mobile-view> <!-- Header and Footer --> <kendo-mobile-layout k-id="'default'"> <kendo-mobile-header> <kendo-mobile-nav-bar> <kendo-view-title></kendo-view-title><!-- <kendo-mobile-button class="about-button" k-align="'right'" href="views/about.html">About</kendo-mobile-button> --> </kendo-mobile-nav-bar> </kendo-mobile-header> <kendo-mobile-footer> <kendo-mobile-tab-strip> <a href="#!accounts" data-icon="home">Home</a> <a href="#!" data-icon="organize">View All</a> <a href="#!" data-icon="more">More</a> </kendo-mobile-tab-strip> </kendo-mobile-footer> </kendo-mobile-layout> <!-- Templates --> <script id="accountsTemplate" type="text/x-kendo-template"> <kendo-mobile-button data-item-id="{{dataItem.custno}}"> {{ dataItem.custname }} </kendo-mobile-button> </script> <!-- Standard Worklight Stuff --> <script src="js/initOptions.js"></script> <script src="js/main.js"></script> <script src="js/messages.js"></script> <script type="text/javascript"> WL.Logger.debug("Loading main page"); </script> </body></html>myApp .run(['myAccounts', function(myAccounts){ myAccounts.init(); }]) .service('myAccounts', function() { this.init = function() { // the application DataSource this.accountsDataSource = new kendo.data.DataSource({ data : [{custname: 'JK',custno:'123'},{custname: 'DH',custno:'1234'}] }); // invoke adapter to get data var invocationData = { adapter : 'AccountsAdapter', // adapter name procedure : 'getAccounts', // procedure name parameters : [] // parameters if any }; WL.Client.invokeProcedure(invocationData,{ onSuccess : function(result) { // REST service results data is in result.invocationResult.customers }, onFailure : function(result) { WL.SimpleDialog.show("Error","The service is temporarily not available. Please try again later.",[{text: "OK"}]); } }); // observable array that will be used to store accounts that user has selected this.added = new kendo.data.ObservableArray([]); // field that will hold reference to the last selected account (used for displaying the details) this.currentItem = null; }; this.setCurrentItem = function(id) { this.currentItem = this.accountsDataSource.get(id); }; }) .factory('templates', function() { return { accountsTemplate: $("#accountsTemplate").html() }; });myApp .controller('AccountsController', ['$scope', 'myAccounts', 'templates', function($scope, myAccounts, templates) { $scope.myAccounts = myAccounts; $scope.templates = templates; }]);We are experiencing a crippling memory leak using a Kendo Grid. We are using the knockout-kendo.js library to bind a Kendo Grid to an existing Knockout observable array such that the grid responds to row insertions and removals in the array.
Attached is a stand-alone example page that demonstrates the issue. Basically, this sample binds an array of objects with observable fields, and a button removes the first item in the array. If you load it you should see the grid of test values. If you keep pressing the button and watch your Task Manager, you should see the memory usage of the browser slowly climbing (we've confirmed that it happens in IE10, IE11, and Firefox). The grid in the real app is bigger so the memory leak gets big enough to crash IE10 after a relatively small number of operations.
This is a high-priority issue, so any help you can give
us would be greatly appreciated!
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script src="Scripts/jquery-1.8.2.js"></script>
<script src="Scripts/kendo.all.js"></script>
<script src="Scripts/knockout-3.2.0.js"></script>
<script src="Scripts/knockout-kendo.js"></script>
</head>
<body>
<script id="Row-Template" type="text/html">
<tr data-uid="#: uid #">
<td data-bind="text: col1"></td>
<td data-bind="text: col2"></td>
<td data-bind="text: col3"></td>
<td data-bind="text: col4"></td>
<td data-bind="text: col5"></td>
<td data-bind="text: col6"></td>
<td data-bind="text: col7"></td>
<td data-bind="text: col8"></td>
<td data-bind="text: col9"></td>
</tr>
</script>
<div>
<button data-bind="click: OnClick">Remove One</button>
</div>
<div data-bind="kendoGrid:
{
editable: false,
data: Rows,
rowTemplate: 'Row-Template',
useKOTemplates: true,
sortable: false,
scrollable: true,
columns:
[
{ title: 'col1', width: '50px' },
{ title: 'col2', width: '50px' },
{ title: 'col3', width: '50px' },
{ title: 'col4', width: '50px' },
{ title: 'col5', width: '50px' },
{ title: 'col6', width: '50px' },
{ title: 'col7', width: '50px' },
{ title: 'col8', width: '50px' },
{ title: 'col9', width: '50px' }
]
}">
</div>
<script type="text/javascript">
function ViewModel() {
var self = this;
var rows = [];
for (var i = 0; i < 100; i++) {
rows.push({ col1: ko.observable("test"), col2: ko.observable("test"), col3: ko.observable("test"), col4: ko.observable("test"), col5: ko.observable("test"), col6: ko.observable("test"), col7: ko.observable("test"), col8: ko.observable("test"), col9: ko.observable("test")});
}
self.Rows = ko.observableArray(rows);
self.OnClick = function () {
self.Rows.remove(self.Rows()[0]);
};
}
ko.applyBindings(new ViewModel());
</script>
</body>
</html>