theChampion
theChampion

Reputation: 4457

Observable Binding With Knockout.JS

When I run this html page and click on some option from select element the value of price automatically changes. How it is possible ? Can you explain the function and what role value of select elementvalue: meal, play here ?

<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8" />
    <title>Working with Lists and Collections</title>

    <script type="text/javascript" src="knockout-3.1.0.debug.js"></script>

    <script type="text/javascript">
        function SeatReservation(name, initialMeal) {
            var self = this;
            self.name = name;
            self.meal = ko.observable(initialMeal);
        }

        // Overall viewmodel for this screen, along with initial state
        function ReservationsViewModel() {
            var self = this;

            // Non-editable catalog data - would come from the server
            self.availableMeals = [
                { mealName: "Standard (sandwich)", price: 0 },
                { mealName: "Premium (lobster)", price: 34.95 },
                { mealName: "Ultimate (whole zebra)", price: 290 }
            ];

            // Editable data
            self.seats = ko.observableArray([
                new SeatReservation("Steve", self.availableMeals[0]),
                new SeatReservation("Bert", self.availableMeals[0])
            ]);

            // Operations
            self.addSeat = function () {
                self.seats.push(new SeatReservation("", self.availableMeals[0]));
            }
        }
    </script>

</head>
<body>
    <div>
        <h2>Your seat reservations</h2>
        <table>
            <thead>
                <tr>
                    <th>Passenger name</th>
                    <th>Meal</th>
                    <th>Surcharge</th>
                    <th></th>
                </tr>
            </thead>
            <tbody data-bind="foreach: seats">
                <tr>
                    <td>
                        <input data-bind="value: name" /></td>
                    <td>
                        <select data-bind="options: $root.availableMeals, value: meal, optionsText: 'mealName'"></select></td>
                    <td data-bind="text: meal().price"></td>
                </tr>
            </tbody>
        </table>
        <button data-bind="click: addSeat">Reserve another seat</button>
    </div>
    <script type="text/javascript">
        ko.applyBindings(new ReservationsViewModel());
    </script>
</body>
</html>

Upvotes: 0

Views: 166

Answers (1)

Tanner
Tanner

Reputation: 22733

This is how knockout is designed to work. I'd suggest going through the Knockout Tutorials to understand it better.

But in answer to your question, your select is set to display: $root.availableMeals, which is an Array of all meals, defined:

self.availableMeals = [
        { mealName: "Standard (sandwich)", price: 0 },
        { mealName: "Premium (lobster)", price: 34.95 },
        { mealName: "Ultimate (whole zebra)", price: 290 }
    ];

Each item in the array has 2 properties: mealName, which is the display value in the select and price, which is used in the Surcharge column. The display value is set with: optionsText: 'mealName'.

Your UI allows you to select an option from this list, and the selection is saved using: value: meal, which is defined as an observable per seat reservation, defined with a default value:

self.meal = ko.observable(initialMeal);

Once a selection is made and this value has been updated, knockout gets to work on the value to display on the Surcharge column.

Because the meal choice has been updated and it's observable, the price automatically changes to be in line with the meal selection, as your binding is configured to return the price of the selected meal for the seat reservation.

<td data-bind="text: meal().price"></td>

JSFiddle For Reference

Upvotes: 2

Related Questions