0
votes

I am serializing a .Net object into a javascript object to use with Knockout. I am trying to use the mapping plugin for Knockout to build the view model without having to specify all of the observable and observableArray properties of my knockout view model. The page will build the view model, load the data, and build a basic table.

This is working great. I have bound a click event to one of the columns which when clicked sends the entire view model to the controller along with the selected client. The result of the code is that one record is removed from the ProbationOfficeWideQueueItems collection, which I have been able to verify by checking the value returned in the ajax call.

The problem I am having is the view model does not seem to get updated with the ko.mapping.fromJS call. I have checked the documentation and multiple other stack overflow posts and cannot find anything wrong:

Here is the entire page, both HTML and Javascript:

<div id="probationOfficeWideQueue-@ViewData("UniqueID")">
<table id="data-grid-@ViewData("UniqueID")" class="data-grid-@ViewData("UniqueID")">
    <thead>
        <tr>
            <th>Client Number</th>
            <th>Client Name</th>
            <th>Officer</th>
            <th>Check In</th>
            <th>Send To</th>
        </tr>
    </thead>
    <tbody data-bind="foreach: ProbationOfficeWideQueueItems">
        <tr>
            <td data-bind="text: ClientNumber"></td>
            <td data-bind="text: ClientName"></td>
            <td data-bind="text: Officer"></td>
            <td data-bind="click: $root.checkInClient"></td>
            <td><input data-bind="value: SendToOfficer, text: Officer" /></td>
        </tr>
    </tbody>
</table>

<script type="text/javascript">
var viewModel = @Html.Raw(New JavaScriptSerializer().Serialize(Model));

function ProbationOfficeWideQueueViewModel(data) {
    var self = this;

    ko.mapping.fromJS(data, {}, self);

    self.checkInClient = function(row) {
        openLoadScreen();
        self.SelectedClientPIN = row.ClientPIN;

        $.ajax({
            type: "POST",
            url: getRoot() + "Probation/ProbationOfficeWideQueue/CheckInClient",
            data: ko.toJSON(self),
            contentType: "application/json",
            success: function(results){
                ko.mapping.fromJS(results, self)
                closeLoadScreen();
            },
            error: function(error){
                closeLoadScreen();
            }
        });
    }
};

function EnhanceDataTable() {
    $('.data-grid-@ViewData("UniqueID")').dataTable({
        "bPaginate": false,
        "bLengthChange": false,
        "aaSorting": [[1, 'asc'], [2, 'asc']],
        "oLanguage": {
            "sSearch": "Filter: "
        },
        "fnDrawCallback": function(){
            $('table.data-grid td').bind('mouseenter', function () { $(this).parent().children().each(function(){$(this).addClass('dataTableRowHighlight');}); });
            $('table.data-grid td').bind('mouseleave', function () { $(this).parent().children().each(function(){$(this).removeClass('dataTableRowHighlight');}); });
        }
    });
};

ko.applyBindings(new ProbationOfficeWideQueueViewModel(viewModel), $("#probationOfficeWideQueue-@ViewData("UniqueID")")[0]);
EnhanceDataTable();

The table rows update properly if I use knockout without the mapper plugin, defining and populating the observable properties and arrays and is my fall back plan. Please let me know where I have gone wrong.

Edit: After initial feedback I want to say that I have tried with the semi colon on the ko.mapping.fromJS(results, self) line in the success function of my ajax call. I have also tried the following changes to the line in my success method:

  • self = ko.mapping.fromJS(results);
  • self = ko.mapping.fromJS(results, {}, self);
  • ko.mapping.fromJS(results, {}, self);
  • ko.mapping.fromJSON(results, {}, self);

I have also tried assigning it to a Model property like one of the examples:

  • self.Model = ko.mapping.fromJS(results, {}, self);

I have also tried this after disabling the DataTables.net plugin on the table.

2

2 Answers

0
votes

jQuery Datatables isn't auto-magically updated when knockout changes something.

it appears they are supposed to implement code that would make the following work:

$('.data-grid-123').dataTable('refresh');
0
votes

You aren't capturing the mapping result into the komodel:

ko.mapping.fromJS(results, self)

based on Knockout.js ko.mapping.toJS not refreshing data in my view it looks like it should be

ko.mapping.fromJS(data, {}, contract_model);