fatih
fatih

Reputation: 3

ko.observable variable in collections tutorial

While analyzing the collections tutorial, I couldn't understand two points:

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

Answers (2)

TMcManemy
TMcManemy

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

Anthony Chu
Anthony Chu

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

Related Questions