I have a KendoUI grid that is defined in my code using the Knockout-Kendo plugin as follow. It is important to note that this grids number of columns changes depending on the json received from the server.
<script type="text/html" id="grid">
<div class="grid-input input" data-bind="kendoGrid:
{
data: RowList,
columns: ko.toJS(GridHeader.ColumnDefinitionList),
rowTemplate: 'kendoui-grid-row',
altRowTemplate: 'kendoui-alt-grid-row',
useKOTemplates: true,
scrollable: false,
pageable: { pageSize: 10 },
sortable: true
}"></div>
</script>
<script type="text/html" id="kendoui-grid-row">
<tr data-bind="visible: IsDeleted() == false, template: { name: 'grid-row' }"></tr>
</script>
<script type="text/html" id="kendoui-alt-grid-row">
<tr data-bind="visible: IsDeleted() == false, template: { name: 'grid-row' }" class="k-alt"></tr>
</script>
<script type="text/html" id="grid-row">
<td><div class="grid-button delete-row-button"><span class="icon-delete"></span></div></td>
<!-- ko foreach: CellList -->
<td data-bind="template: { name: Input.Type, data: Input }">
</td>
<!-- /ko -->
</script>
<script type="text/html" id="text">
<input class="text-input input k-textbox" data-bind="value: Value" />
</script>
In this case, I have a grid filled with text boxes (in each cells of the grid, there is an input of type text). Now my problem is that sorting by clicking the grid headers does nothing even if there is texts in the inputs. What I would like to do is be able to define the target of the sorting. In this case it would be the value of the input inside the grid cells.
I've ran into a similar problem a while ago. The problem was that the Kendo Grid doesn't work well with ko observables. As a workaround you can create a computed which returns the data as a plain JS object:
this.RowList.asJS = ko.computed(function() {
return ko.toJS(this.RowList());
}, this);
Then change data: RowList
with the following:
data: RowList.asJS
This however means you lose the observables in your row templates. A workaround for this is to get the original object again inside your row.
First create a helper function to quickly get an item by ID (assuming you have an Id property):
this.RowList.getById = function(id) {
return ko.utils.arrayFirst(this.RowList(), function(row) {
return ko.unwrap(row.Id) === id;
});
}, this);
Now you can call getById
inside your row templates:
<script type="text/html" id="kendoui-grid-row">
<!-- ko with: $root.RowList.getById(Id) -->
<tr data-bind="visible: IsDeleted() == false, template: { name: 'grid-row' }"></tr>
<!-- /ko -->
</script>