JSFiddle - React, Tailwind, and code Playground
by rniemeyer
HTML
<div data-bind="with: product">
<button data-bind="click: beginEdit">Edit</button>
<button data-bind="click: endEdit">Cancel</button>
<input type="checkbox" data-bind="checked: amIEditing" disabled
/>
<input type="text" data-bind="value: name" />
<hr />
<div data-bind="foreach: variants">
<div>
<button data-bind="click: beginEdit">Edit</button>
<button data-bind="click: endEdit">Cancel</button>
<input type="checkbox" data-bind="checked: amIEditing" disabled
/>
<input type="text" data-bind="value: name" />
</div>
</div>
</div>
<pre data-bind="text: ko.toJSON($root, null, 2)"></pre>
JavaScript
var Entity = function () {
this.name = ko.observable("default");
this.meta = {};
this.meta.original = ko.observable();
this.meta.isEditing = ko.observable(false);
};
ko.utils.extend(Entity.prototype, {
beginEdit: function () {
this.meta.isEditing(true);
},
endEdit: function () {
this.meta.isEditing(false);
},
init: function (data) {
this.name(data.name || "");
this.meta.original(data || {});
}
});
var Product = function (data) {
var initial = data || {};
this.variants = ko.observableArray();
Entity.call(this, data);
this.init(initial);
if (initial.variants !== null) {
for (var i = 0; i < initial.variants.length; i++) {
// NOTE: this is the misterious line. Creating two instances
// of 'new Variant', ends up pushing a single instance.
this.variants.push(new Variant(initial.variants[i]));
//-----------------------------------------------------------
alert(this.variants()[i].name());
}
}
this.amIEditing = ko.computed(function () {
return this.meta.isEditing();
}, this, {
deferEvaluation: true
});
};
var Variant = function (data) {
var initial = data || {};
Entity.call(this, data);
this.init(initial);
this.amIEditing = ko.computed(function () {
return this.meta.isEditing();
}, this, {
deferEvaluation: true
});
};
Product.prototype = Object.create(Entity.prototype);
Variant.prototype = Object.create(Entity.prototype);
var viewModel = function () {
var self = this;
self.product = new Product({
name: "luigi",
variants: [{
name: "first"
}, {
name: "second"
}]
});
};
ko.applyBindings(new viewModel());