0

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;
        }
        ));
Vishal Avalani
  • 381
  • 3
  • 14
  • 1
    have you tried this `employeeViewModel.employees(ko.mapping.fromJS(data))` `mapping` plugin all it does is make plane json data to observables . cheers – super cool Jun 05 '15 at 06:28
  • check this sample which gives you idea http://jsfiddle.net/supercool/LkqTU/24514/ . cheers – super cool Jun 05 '15 at 06:35
  • You should not use "new function". http://stackoverflow.com/a/10406585/1048572 – Roy J Jun 05 '15 at 11:07
  • It is still not working. This is html code. It is appearing in ViewModel but not getting binded in data-bind="foreach:employees" - Nothing is returned. – Vishal Avalani Jun 05 '15 at 16:26

1 Answers1

1

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/

Roy J
  • 42,522
  • 10
  • 78
  • 102