Reputation: 1945
I have html table which i bind to using knockout observable array TableDataList
like below
<div style="overflow: hidden;margin-top: 30px;margin-left: 10px;float:left;" >
<table style="width: 100%" >
<thead>
<tr>
<th style="padding: 0px">Id </th>
<th style="padding: 0px">Name</th>
</tr>
</thead>
</table>
<div style="overflow: auto;height: 490px;">
<table id ="Table1" style="width: 100%;" >
<tbody data-bind="foreach: TableDataList">
<tr data-bind= "click: $root.giveDetails">
<td style="padding: 0px;text-align: left" data-bind="text: Id"></td>
<td style="padding: 0px;" data-bind="text: Name "></td>
</tr>
</tbody>
</table>
</div>
</div>
Currently i am loading about 5000 rows in table but it takes about 5 seconds to click the row. I have knockout binding on click event data-bind= "click: $root.giveDetails"
of row which calls some service and loads data
I can see that when i click on row it loads data first and then marks the row. I highlight row with blue color when it is clicked. When the data is less in table then there is no problem but performance degrades when there is about 5000 records. Can someone point me to tips on how to improve this?
Update 1
This is click event of my tr
this.giveDetails= function (item) {
$.ajax({
url: "../Service/Table/TableData",
type: "PUT",
contentType: 'application/json',
processData: false,
data: JSON.stringify(item.Id()),
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert(errorThrown);
},
success: function (allData) {
var mappedData= $.map(allData, function (item) {
return new TableData(item);
});
self.AnotherTableDataList(mappedData);
}
});
});
Upvotes: 0
Views: 133
Reputation: 8110
I think the problem may be in large amount of event handlers (one per each of 5000 rows). So the idea is to bind click event to table body and then on in your giveDetails
function you need to calculate what exact row was clicked. Like this:
...
<table id ="Table1" style="width: 100%;" >
<tbody data-bind="foreach: TableDataList, click: $root.giveDetails">
<tr>
<td style="padding: 0px;text-align: left" data-bind="text: Id"></td>
<td style="padding: 0px;" data-bind="text: Name "></td>
</tr>
</tbody>
</table>
... And later in your model:
giveDetails: function(data, e) {
alert($(e.target).parents('tr').find('td:first').text());
}
Now this is not really a good practise to mix knockout viewmodels with jQuery code, but this is the starting idea, maybe there's a better solution. Here is demo with 5000 rows. Feel free to update this code, let's solve this problem together :)
I refactored my code a little to get item
inside click handler:
giveDetails: function(data, e) {
if ($(e.target).prop("tagName") != 'TD')
return;
var id = $(e.target).closest('tr').find('td:first').text();
var item = ko.utils.arrayFirst(this.TableDataList(), function(arrayItem) {
return arrayItem.Id == id;
});
alert(item.Id + ', ' + item.Name);
}
Demo link is the same.
Upvotes: 1