Mapping not working with api call

246 views Asked by At

I want to make all inner employee properties as observable so I've tried the knockout mapping plugin. However, after using it data is not getting bound properly. Here is the javascript code:

var employeeViewModel = new function () {
    var self = this;
    self.employees = ko.observableArray();
    self.loading = ko.observable(true);
}();

$(document).ready(function () {
    ko.applyBindings(employeeViewModel);
    GetEmployees();
});

function GetEmployees()
{
    $.get('/api/Employees', null, function (data) {
        if (employeeViewModel.employees.length == 0) {
            employeeViewModel.employees = ko.mapping.fromJS(data);
        }
        else {
            ko.mapping.fromJS(data, employeeViewModel.employees);
        }
        //employeeViewModel.employees(data); //This works but want to make all inner properties as observable
        employeeViewModel.loading(false);
    });
}

HTML Code:

<div class="loadingImg" data-bind="visible: loading()"></div>
<table class="table table-bordered" data-bind="visible: !loading()">
    <thead>
        <tr>
            <th>Name</th>
            <th>Email</th>
            <th>Salary</th>
        </tr>
    </thead>
    <tbody data-bind="foreach:employees">
        <tr data-bind="template: {name: 'edit-template', data: $data }"></tr>
    </tbody>
</table>

<script type="text/html" id="display-template">
    <td data-bind="text: Name"></td>
    <td data-bind="text: Email"></td>
    <td data-bind="moneyFormat: Salary"></td>
</script>
<script type="text/html" id="edit-template">
    <td><input class="form-control" type="text" data-bind="value: Name" /></td>
    <td><input class="form-control" type="text" data-bind="value: Email" /></td>
    <td><input class="form-control" type="text" data-bind="value: Salary" /></td>
</script>

The main issue is that it is appearing but not getting binded somehow. Here is the result: -

enter image description here

Below code works but how to achieve same via mapping plugin? I thought we can do same in 1 line by mapping plugin but it is not working.!! Need help.. May be I am missing something here..

        employeeViewModel.employees(ko.utils.arrayMap(data, function (employee) {
            var obsEmployee = {
                Name: ko.observable(employee.Name),
                Email: ko.observable(employee.Email),
                Salary: ko.observable(employee.Salary)
            }
            return obsEmployee;
        }
        ));

1

There are 1 answers

0
Roy J On BEST ANSWER

Don't create the employees observableArray. It's getting bound by applyBindings, then you re-assign it from ko.mapping.fromJS. You'll need to use an if binding instead of visible to prevent knockout from trying to access employees before it has been mapped and bound.

<table class="table table-bordered" data-bind="if: !loading()">

Example: http://jsfiddle.net/qxc19joy/