Reputation: 3
While analyzing the collections tutorial, I couldn't understand two points:
why do we have to define initialMeal variable as ko.observable in SeatReservation function? If I remove ko.observable, foreach loop in the View doesn't work.
initialMeal is an array. Therefore, ko.observableArray should be used. However, ko.observableArray does not work.
I discovered a similar pattern in this example. Could you help me to clarify this issue? Thanks.
View
<table>
<thead><tr>
<th>Passenger name</th><th>Meal</th><th>Surcharge</th><th></th>
</tr></thead>
<tbody data-bind="foreach: seats">
<tr>
<td data-bind="text: name"></td>
<td data-bind="text: meal().mealName"></td>
<td data-bind="text: meal().price"></td>
</tr>
</tbody>
</table>
ViewModel
function SeatReservation(name, initialMeal) {
var self = this;
self.name = name;
self.meal = ko.observable(initialMeal);
}
function ReservationsViewModel() {
var self = this;
self.availableMeals = [
{ mealName: "Standard (sandwich)", price: 0 },
{ mealName: "Premium (lobster)", price: 34.95 },
{ mealName: "Ultimate (whole zebra)", price: 290 }
];
self.seats = ko.observableArray([
new SeatReservation("Steve", self.availableMeals[0]),
new SeatReservation("Bert", self.availableMeals[0])
]);
self.addSeat = function() {
self.seats.push(new SeatReservation("", self.availableMeals[0]));
}
}
ko.applyBindings(new ReservationsViewModel());
Upvotes: 0
Views: 129
Reputation: 824
From a cursory look, it doesn't appear as though you've seen this particular tutorial all the way through. I think completing the tutorial will clear some things up for you. With that being said, here are the answers to the questions you asked:
Why do we have to define initialMeal variable as ko.observable in SeatReservation function? ? If I remove ko.observable, foreach loop in the View doesn't work.
Given the markup you included, there is no reason that meal needs to be initialized as an observable. In fact, you could simply initialize meal to initialMeal (in the SeatReservation constructor function) and remove the function invocation syntax (parenthesis) from the mealName and price data bindings (in the view).
Remember that observable variables are all about notifying subscribers of changes to their values. Since, in your example, there is no way to modify a meal for a particular seat reservation, there is no reason to initialize meal as an observable. However, if you were to progress further in the tutorial, you would find that meal does need to be initialized as an observable value.
Also, you should note that observables are actually functions. In order to read the value of an observable, you must call the observable with no parameters (e.g. meal()).
InitialMeal is an array. Therefore, ko.observableArray should be used. However, ko.observableArray does not work.
InitialMeal is actually an object, not an array. Look again at the ReservationsViewModel constructor function. The value that is being passed to the SeatReservation constructor function is the first element from the availableMeals array, not the array itself.
Upvotes: 0
Reputation: 37550
why do we have to define initialMeal variable as ko.observable in SeatReservation function? If I remove ko.observable, foreach loop in the View doesn't work.
It's not working when it's not an observable because the bindings meal().mealName
and meal().price
still expect observables. Change them to meal.mealName
and meal.price
and the bindings will work.
Note that if you don't use observables, the bindings are one-way and will not be updated if the underlying model values are changed after the page is loaded.
initialMeal is an array. Therefore, ko.observableArray should be used. However, ko.observableArray does not work.
initialMeal
is not an array, it's an element in the self.availableMeals
array, which is an object (e.g. { mealName: "Standard (sandwich)", price: 0 }
).
Upvotes: 2