Reputation: 1096
I have a simple training case with knockout.js where I want to show a different number of apples depending on the range slider value. Here is the slider:
<input data-bind="value: currentAppleCount" type="range" step="1" min="2" max="10"/>
Every time a user moves the slider handle, a part of UI should be redrawn with an appropriate number of apples using some method like renderApples(appleCount)
.
Should I use model.currentAppleCount.subscribe(renderApples) or there is a better approach, because this case is trivial and knockoutjs documentation states "You won’t normally need to set up subscriptions manually". Also, as a matter of good practice, should renderApples
method receive appleCount
as an argument or access model.currentAppleCount
observable directly.
EDIT:
Problem is that I need to work with a third party api with add and remove methods.
Upvotes: 2
Views: 191
Reputation: 3192
If you're working with a third party API, such as a jQueryUI widget or something similar, then setting up a subscription seems like the right thing to do.
I'm guessing that your third party API does not understand knockout, and thus doesn't know how to deal with observables. Setting up a subscription allows you to have your own code that will get the updated value from the observable and pass it on to the API.
model.currentAppleCount.subscribe(function(newValue) {
someOtherAPI.UpdateAppleCount(newValue);
});
You are right, the documentation says:
You won’t normally need to set up subscriptions manually, so beginners should skip this section
This means you're no longer a beginner. :)
P.S. If your third party API has the ability to update the value of the appleCount, be sure to hook into some type of update event that they provide and then set the observable from there. Something like:
// I'm just making up the OnAppleCountUpdate event. I have
// no idea what it might be called in the third party API.
someOtherAPI.OnAppleCountUpdate(function(newValueFromAPI) {
model.currentAppleCount(newValueFromAPI);
});
This will allow you to have two-way binding between the HTML/KO pieces and your third party API.
Upvotes: 1
Reputation: 89181
Use a ko.computed
to return an array of appropriate length. The computed property will be reevaluated each time the referenced observables are updated.
function ViewModel() {
this.currentAppleCount = ko.observable(2);
this.apples = ko.computed(function () {
var currentAppleCount = this.currentAppleCount();
var apples = [];
for (var i = 1; i <= currentAppleCount; i++) {
apples.push(i);
}
return apples;
}, this);
}
ko.applyBindings(new ViewModel());
Alternatively, you could return a slice of a full array. This way you would preserve the object instances.
<input data-bind="value: currentAppleCount" type="range" step="1" min="2" max="10"/>
<ul data-bind="foreach: apples">
<li>Apple #<span data-bind="text: $data"></span></li>
</ul>
http://jsfiddle.net/MizardX/KeHKB/
Upvotes: 2