Reputation: 121
In this jsfiddle I have a simple example of what I want to do working. It's all working just fine. But it seems like there has to be a better way to create these arrays with some loops or something. I've been trying all day and haven't succeeded. Can someone tell me if
Here's the code from the fiddle.
View:
<table>
<tbody>
<tr>
<td></td>
<!-- ko foreach: topvals -->
<td >
<input type="text" data-bind="value: val"/>
</td>
<!-- /ko -->
</tr>
<tr>
<td><input type="text" data-bind="value:sidevals()[0].val"/></td>
<!-- ko foreach: intersections()[0] -->
<td><span data-bind="text: val"></span></td>
<!-- /ko -->
</tr>
<tr>
<td ><input type="text" data-bind="value:sidevals()[1].val"/></td>
<!-- ko foreach: intersections()[1] -->
<td><span data-bind="text: val"></span></td>
<!-- /ko -->
</tr>
</tbody>
</table>
Viewmodel:
function ViewModel() {
this.topvals = ko.observableArray([
{ val: ko.observable(6) },
{ val: ko.observable(1) },
{ val: ko.observable(1) },
{ val: ko.observable(1) }
]);
this.sidevals = ko.observableArray([
{ val: ko.observable(1) },
{ val: ko.observable(1) },
{ val: ko.observable(1) }
]);
this.intersections = ko.observableArray([
[
{ val: ko.computed(function () { return this.topvals()[0].val() * this.sidevals()[0].val(); }, this) },
{ val: ko.computed(function () { return this.topvals()[1].val() * this.sidevals()[0].val(); }, this) },
{ val: ko.computed(function () { return this.topvals()[2].val() * this.sidevals()[0].val(); }, this) },
{ val: ko.computed(function () { return this.topvals()[3].val() * this.sidevals()[0].val(); }, this) }
],
[
{ val: ko.computed(function () { return this.topvals()[0].val() * this.sidevals()[1].val(); }, this) },
{ val: ko.computed(function () { return this.topvals()[1].val() * this.sidevals()[1].val(); }, this) },
{ val: ko.computed(function () { return this.topvals()[2].val() * this.sidevals()[1].val(); }, this) },
{ val: ko.computed(function () { return this.topvals()[3].val() * this.sidevals()[1].val(); }, this) }
]
]);
}
ko.applyBindings(new ViewModel());
Upvotes: 5
Views: 147
Reputation: 338228
This simple view model already does it:
function ViewModel(vals1, vals2) {
this.topvals = ko.observableArray(mapToObservables(vals1));
this.sidevals = ko.observableArray(mapToObservables(vals2));
this.calc = function (val1, val2) {
return ko.unwrap(val1) * ko.unwrap(val2);
};
}
ko.applyBindings(new ViewModel([6, 5, 4, 3], [1, 2, 3]));
where mapToObservables
stands for either the mapping plugin or a function like this one:
function mapToObservables(vals) {
return ko.utils.arrayMap(vals, function (val) {
return { val: ko.observable(val) };
});
};
and this view
<table>
<tbody>
<tr>
<td></td>
<!-- ko foreach: topvals -->
<td><input type="text" data-bind="value: val"/></td>
<!-- /ko -->
</tr>
<!-- ko foreach: sidevals -->
<tr>
<td><input type="text" data-bind="value: val"/></td>
<!-- ko foreach: $root.topvals -->
<td><span data-bind="text: $root.calc(val, $parent.val)"></span></td>
<!-- /ko -->
</tr>
<!-- /ko -->
</tbody>
</table>
See: http://jsfiddle.net/dt9kL/
A variant would be to use a separate sub-model for the values: http://jsfiddle.net/dt9kL/1/. For encapsulating a single value this is overkill, but it might be useful for more complex structures.
Upvotes: 1
Reputation: 11403
topvals
and sidevals
arrays you can use ko.mapping.fromJS.intersections
you can return an "array of arrays" using the ko.utils.arrayMap function.Here is the final code (and a jsfiddle):
function ViewModel() {
var self = this;
var calculateIntersection = function(topval, sideval) {
return topval * sideval;
};
var topvals = [{ val: 1 }, { val: 2 }, { val: 3 }];
var sidevals = [{ val: 1 }, { val: 2 }, { val: 3 }];
self.topvals = ko.mapping.fromJS(topvals);
self.sidevals = ko.mapping.fromJS(sidevals);
self.intersections = ko.computed(function() {
return ko.utils.arrayMap(self.sidevals(), function(sideval) {
return ko.utils.arrayMap(self.topvals(), function(topval) {
return calculateIntersection(topval.val(), sideval.val());
});
});
});
}
ko.applyBindings(new ViewModel());
And here is the view:
<table>
<tbody>
<tr>
<td></td>
<!-- ko foreach: topvals -->
<td >
<input type="text" data-bind="value: val"/>
</td>
<!-- /ko -->
</tr>
<!-- ko foreach: sidevals -->
<tr>
<td><input type="text" data-bind="value: val"/></td>
<!-- ko foreach: $root.intersections()[$index()] -->
<td><span data-bind="text: $data"></span></td>
<!-- /ko -->
</tr>
<!-- /ko -->
</tbody>
</table>
Upvotes: 3