I’m trying to think of the most elegant way to do this using knockout js.
Say I need to sum up 3 values, but the result sum can also be edited…how would you do this using knockout js?
I was thinking along the lines of setting deactivating the values that make up the sum when a user edits the sum value and reactivating them if the sum field is blank.
See this jsfiddle for a starting point: http://jsfiddle.net/faHHB/
A similar example for decomposing a string using a computed observable exists in the knockout documentation:
function MyViewModel() {
this.firstName = ko.observable('Planet');
this.lastName = ko.observable('Earth');
this.fullName = ko.computed({
read: function () {
return this.firstName() + " " + this.lastName();
},
write: function (value) {
var lastSpacePos = value.lastIndexOf(" ");
if (lastSpacePos > 0) { // Ignore values with no space character
this.firstName(value.substring(0, lastSpacePos)); // Update "firstName"
this.lastName(value.substring(lastSpacePos + 1)); // Update "lastName"
}
},
owner: this
});
}
ko.applyBindings(new MyViewModel());
Edit
For more clarity, I’m not sure how best to represent this situation:
Imagine the 3 fields represent value of your house, value of your car, value of your retirement savings and the sum represents total value of your assets.
All fields should be editable, and if a user enters the 3 values the total value should be calculated. The total value can also be directly edited (incase the user has other savings that aren’t listed). I’m not sure of the best way to represent this…
When the user edits the total, options I can think of are:
- Divide the total by 3 and populate the other values
- Grey out the input values, and only allow users to change them again when the total value is blank.
- Have a checkbox labelled calculate, which sums the value when ticked and lets the user edit when unticked.
I was trying to ask what the best way to represent this situation is as well as how to implement it using knockout. Apologies if I wasn’t clear.
I’ve settled on approach 3 for now: jsfiddle.net/faHHB/10
You probably want a view model that:-
Holds the sum as a separate observable
Has a flag to determine whether the sum should be automatically computed
Calculates the value of editedTotal when the flag is true, otherwise just returns the present value.
When you detect a direct edit on
self.editedTotal, setself.autoCalculateto false. At that point, your VM will not attempt to recalculate, and will just return the tracked value.