I am newbie to knockoutjs . i was trying to map json data to ko. This is my code.
I want to parse the json data and display it in the table. When i am trying ko.compute it throws me self.firstName() is not an function. When i try to log the value of the firstName in console before compute function, it prints the 3 values in the json array and runs the forurth time and throws an error saying self.firstName is not an function.
Edit :When i remove computed and just print the data as in the json it is able to map correctly. the issue occurs when i use computed. When i try console.log(self.firstName() ) before computed and after mapping it prints the values in the jsonarray but instead of parsing 3 times its parses 4 times and 4th time it gives me the "not a function" error
<div id="employeeList">
<table border ="2">
<thead>
<tr>
<th> First Name</th>
<th> Last Name</th>
<th> Age</th>
<th> Phone</th>
<th> Email</th>
</tr>
</thead>
<tbody data-bind="foreach:employees">
<tr>
<td data-bind="text:name"></td>
<td data-bind="text:firstName"></td>
<td data-bind="text:lastName"></td>
<td data-bind="text:age"></td>
<td data-bind="text:phone"></td>
<td data-bind="text:email"></td>
</tr>
</tbody>
</table>
</div>
This is my js code
var personMapping={
'copy':['age'],
'employees': {
create: function(options) {
return new PersonViewModel(options.data);
}
}
};
function PersonViewModel(data){
var self=this;
ko.mapping.fromJS(data,personMapping,this);
self.name=ko.computed(function(){
return self.firstName()+' '+self.lastName();
},this);
}
var data={employees:
[{
firstName: 'Marco',
lastName: 'Franssen',
age: 26,
phone: 12346789,
email: "a@a.com"
},
{
firstName: 'Kumar',
lastName: 'Rangarajan',
age: 26,
phone: 123467890,
email: "a@b.com"
},
{
firstName: 'A',
lastName: 'B',
age: 26,
phone: 6775675567567,
email: "a@c.com"}]
}
ko.applyBindings(new PersonViewModel(data), $('#employeeList'));
});
This is the jsfiddle code: http://jsfiddle.net/YfqPs/1/
Your code gets executed 4 times because your are reusing your PersonViewModel
as your main view model and your view model in your personMapping
:
Your PersonViewModel
get called 3 items once for each item in your employees
array resulting of this call:
create: function(options) {
return new PersonViewModel(options.data);
}
Your PersonViewModel
get called for the 4 time resulting of this call:
ko.applyBindings(new PersonViewModel(data), $('#employeeList'));
and this time it throws the exception because there is no firstName
property on your main data
only on your employees.
There are multiple ways to fix this but all of them require to create a proper standalone "main" viewmodel.
The easiest solution is to create your "main" viewmodel with var viewModel = ko.mapping.fromJS(data, personMapping);
and use it in your ko.applyBindings
:
var viewModel = ko.mapping.fromJS(data, personMapping);
ko.applyBindings(viewModel, $('#employeeList')[0]);
Demo JSFiddle