JSFiddle - React, Tailwind, and code Playground
by Josh Carroll
HTML
<h2>ListCollection</h2>
<h2>Your seat reservations (<span data-bind="text: seats().length"></span>)</h2>
<table>
<thead>
<tr>
<th>Name</th>
<th>Meal</th>
<th>Price</th>
</tr>
</thead>
<!-- foreach 'seats' in the ReservationsViewModel, 'seats' in the foreach is an array inside the view-model -->
<tbody data-bind="foreach: seats">
<tr>
<!--name: is not a function because it's not an observable property-->
<!--options: comes from the avaialableMeals property of the ReservationViewModel-->
<!--value: comes from the seatReservation class, equivalent to (SeatReservation.meal), it represents the selected value not the <option value="id">
-->
<!--optionsText: comes from availableSeats.mealName of the ReservationViewModel-->
<td>
<input data-bind="value: name" />
</td>
<td>
<select data-bind="
options: $root.availableMeals,
value: meal().mealId,
optionsValue: 'mealId',
optionsText: 'mealName',
optionsCaption: 'Choose...'"></select>
</td>
<td><span data-bind="text: formattedPrice"></span> (<span data-bind="text: meal().mealId"></span>)</td>
<td><a href="#" data-bind="click: forceUpdate">Update</a>
</td>
</tr>
</tbody>
</table>
<button data-bind="click: addSeat, enable: seats().length < 5">Reserve another seat</button>
JavaScript
// Class to represent a row in the seat reservations grid
function SeatReservation(name, initialMeal) {
//var self = this;
//self.name = ko.observable(name);
var $this = this;
this.name = name;
this.meal = ko.observable(initialMeal);
this.mealId = ko.computed(function(){
return this.meal().mealId;
}, this);
this.formattedPrice = ko.computed(function () {
var price = this.meal().price;
return price ? "$" + price.toFixed(2) : "None";
}, this);
this.forceUpdate = function(){
$this.meal.valueHasMutated();
};
}
function ReservationsViewModel(name, meal) {
//var self = this;
// Non-editable catalog data - would come from the server
this.availableMeals = [{
mealId: 1,
mealName: "Standard (sandwich)",
price: 47.55
}, {
mealId: 2,
mealName: "Premium (lobster)",
price: 34.95
}, {
mealId: 3,
mealName: "Ultimate (whole zebra)",
price: 290.123
}];
//editable data
this.seats = ko.observableArray([
new SeatReservation("Randel", this.availableMeals[2]),
new SeatReservation("Knockout", this.availableMeals[1])]);
//operations
this.addSeat = function () {
this.seats.push(new SeatReservation("", this.availableMeals[0]));
};
this.removeSeat = function (seat) {
this.seats.remove(seat);;
}
}
ko.applyBindings(new ReservationsViewModel());