knockoutのcomputed property
Knockout Advent Calendar 2015
by MKGaru
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.3.0/knockout-debug.js"></script>
<script src="https://mbest.github.io/knockout.punches/knockout.punches.js"></script>
<script src="https://rawgit.com/SteveSanderson/knockout-es5/master/dist/knockout-es5.js"></script>
<h1>Fruit Shopping Order</h1>
<div>商品リスト:
<table>
<thead>
<tr>
<th>商品名</th>
<th>単価</th>
<th>注文</th>
</tr>
</thead>
<tbody data-bind="foreach:items">
<tr>
<td>{{name}}</td>
<td>{{price}}</td>
<td>
<button type="button" data-bind="click:$parent.order.add">注文</button>
</td>
</tr>
</tbody>
</table>
</div>
<br>
<div>注文票:
<table data-bind="with:order">
<thead>
<tr>
<th>商品名</th>
<th>単価</th>
<th>数量</th>
<th>小計</th>
<th></th>
</tr>
</thead>
<tbody data-bind="foreach:details">
<tr>
<td>{{item.name}}</td>
<td>{{item.price}}</td>
<td><input type="number" data-bind="value:quantity" min="1" style="width:3em;" /></td>
<td>{{price}}</td>
<td><button type="button" data-bind="on.click:$parent.details.splice($index(),1)">キャンセル</button></td>
</tr>
</tbody>
<tbody data-bind="if:!details.length">
<tr>
<td colspan="5" style="text-align:center">Empty</td>
</tr>
</tbody>
<tfooter>
<tr>
<td colspan="3">合計</td>
<td>{{totalPrice}}</td>
</tr>
</tfooter>
</table>
</div>
CSS
td,input{
text-align:right;
}
JavaScript
function Item(name,price){
this.name = name;
this.price = price;
ko.track(this);
}
function Shop(){
this.items = [
new Item("apple",60),
new Item("banana",25),
new Item("cinnamon",80),
new Item("dragonfruit",120)
];
this.order = new Order();
ko.track(this);
}
function OrderDetail(item,quantity){
this.item=item;
this.quantity=quantity;
ko.track(this);
Object.defineProperty(this,'price',{get:function(){
return this.item.price * this.quantity
}});
}
function Order(){
this.details = [];
ko.track(this);
Object.defineProperty(this,'totalPrice',{get:function(){
var total = 0;
this.details.forEach(function(detail){
total += detail.price;
});
return total;
}});
}
Order.prototype.add=function(item,event){
var quantity = 1;
this.details.push(new OrderDetail(item,quantity));
}
var vm = new Shop();
ko.punches.enableAll();
ko.applyBindings(vm);