JSFiddle - React, Tailwind, and code Playground
HTML
<script src="https://code.jquery.com/jquery-1.11.2.js"></script>
<script src="http://knockoutjs.com/downloads/knockout-3.2.0.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.js"></script>
<select class="form-control" data-bind="options: persons, optionsText: 'name', value:editingPerson,optionsCaption: '-- Select one --'""></select>
<div data-bind="with:editingPerson">
id: <input data-bind="value:id"> <br>
name: <input data-bind="value:name"> <br>
surname: <input data-bind="value:surname"> <br>
Full Name: <input data-bind="value:fullName"> <br>
Address: <input data-bind="value:fullAddress"> <br>
<table>
<thead>
<tr>
<td>price</td>
<td>iva</td>
<td>tax</td>
</tr>
</thead>
<tbody data-bind="foreach:amounts">
<tr>
<td data-bind="text:price"></td>
<td data-bind="text:iva"></td>
<td data-bind="text:tax"></td>
</tr>
</tbody>
</table>
<button data-bind="click:savePerson" type="button">Save</button>
</div>
<textarea data-bind="value:ko.toJSON($root)" cols="100"></textarea>
JavaScript
function Person(id,name,surname,address,amounts){
var self = this;
self.id = ko.observable(id);
self.name = ko.observable(name);
self.surname = ko.observable(surname);
self.address = ko.observable(address);
self.amounts = ko.observableArray(amounts);
self.fullName = ko.computed(function() {
return self.name()+" - "+self.surname();
});
}
function Address(id,street,number){
var self = this;
self.id = ko.observable(id);
self.street = ko.observable(street);
self.number = ko.observable(number);
self.fullAddress = ko.computed(function() {
return self.street()+" - "+self.number();
});
}
function Amount(id,price,iva){
var self = this;
self.id = ko.observable(id);
self.price = ko.observable(price);
self.iva = ko.observable(iva);
self.tax = ko.computed(function() {
var t = parseInt(self.iva(), 10) * parseInt(self.price(), 10);
return t.toString();
});
}
//var mapping = {
// 'Amounts': {
// create: function(options) {
// return new Amount(options.data.tax,options.data.value);
// }
// }
//}
var mapping = {
create: function(options) {
return new Person(options.data.id,options.data.name,options.data.surname,options.data.address,options.data.amounts);
},
'address': {
create: function(options) {
return new Address(options.data.id,options.data.street,options.data.number);
}
},
'Amounts': {
create: function(options) {
return new Amount(options.data.id,options.data.price,options.data.iva);
}
}
};
function PersonViewModel() {
var self = this;
self.persons = ko.mapping.fromJS([]);
self.editingPerson = ko.observable();
self.savePerson = function() {
...