Two-Way Data Binding

แนวคิดเรื่อง Two-Way Data Binding ของ AngularJS คือ ส่วนที่เป็น model กับ view จะเชื่อมโยงกัน

เมื่อมีการเปลี่ยนแปลงค่าที่ส่วนของ Model ส่วนของ View ก็จะเปลี่ยนไปด้วย

และเมื่อมีการเปลี่ยนแปลงค่าที่ส่วนของ View ส่วนของ Model ก็จะเปลี่ยนไปด้วย เช่นกัน

โดยจะมี Directive 2 ตัวที่จะเรียนรู้ในบทนี้คือ ng-click และ ng-class

Ng-Click คือ อะไร ?

Ng-Click เป็น Directive ที่ทำงานเหมือนฟังก์ชั่น click ใน jQuery หรือ onclick ใน html

<div ng-click="การกำหนดค่า/ฟังก์ชั่น">

Ng-Class คือ อะไร ?

Ng-Class เป็น Directive ที่ทำการกำหนด Class ให้กับ HTML tag โดยจะเพิ่ม class ก็ต่อเมื่อเงื่อนไขเป็นจริง

<div ng-class="{'ชื่อ Class' : เงื่อนไข/ฟังก์ชั่น}">

ในไฟล์ app.js ทำการเพิ่ม attribute ให้กับซูชิ คือ Quantity(จำนวน) และลบ attribute canPurchase ออก

$scope.sushis = [
	{
		name: 'Maguro',
		price: 200,
		description: "Fat Tuna",
		quantity: 0,
		image: '../image/sushi/maguro.jpg'
	},...
];		

ในไฟล์ sushistore.html เราจะทำการเพิ่มปุ่ม + - ให้กับซูชิแต่ละชิ้น

และเพิ่มจำนวนที่จะซื้อกับจำนวนทั้งหมดให้กับซูชิแต่ละชิ้น

<div class="list-group" ng-controller="storeController as store" >
	<div class="list-group-item clearfix" ng-repeat="sushi in sushis">
		<h1>{{sushi.name}}
			<em class="pull-right">{{sushi.price | number:2}} yen</em>
		</h1>
		<div class="row">
			<div class="col-md-6"><img ng-src="{{sushi.image}}" /></div>
			<div class="col-md-6">
				<h3><strong>{{sushi.quantity}}</strong></h3>
				<button class="btn btn-default pull-right" ng-show="sushi.canPurchase">สั่งซื้อ</button>
				<button class="btn btn-default">Δ</button>
				<button class="btn btn-default">∇</button>
			</div>
		</div>
	</div>
</div>

สร้างฟังก์ชั่น purchase เช็คว่า Quantity > 0 หรือไม่

สร้างฟังก์ชั่น clickAdd ไว้เพิ่มจำนวนซูชิและ clickRemove ไว้ลดจำนวนซูชิ

โดยทั้ง 3 ฟังก์ชั่นรับตัวแปรจาก sushi

$scope.sushis = [...];
$scope.purchase = function (item) {
	if (item.quantity > 0) {
		return true;
	} else {
		return false;
	}
};
$scope.clickAdd = function (item) {
	item.quantity += 1;
};
$scope.clickRemove = function (item) {
	if (item.quantity > 0) {
		item.quantity -= 1;
		return true;
	} else {
		return false;	
	}
};				

ทำการเปลี่ยนส่วนที่ใช้ sushi.canPurchase มาเป็น sushi.purchase(sushi)

เพิ่ม ng-click ให้กับ ปุ่มเพิ่มและปุ่มลบ

ปุ่มเพิ่ม ทำการเพิ่ม ng-click="clickAdd(sushi)"

ปุ่มลบ ทำการเพิ่ม ng-click="clickRemove(sushi)"

<div class="list-group" ng-controller="storeController as store" >
	<div class="list-group-item clearfix" ng-repeat="sushi in sushis">
		<h1>{{sushi.name}}
			<em class="pull-right">{{sushi.price | number:2}} yen</em>
		</h1>
		<div class="row">
			<div class="col-md-6"><img ng-src="{{sushi.image}}" /></div>
			<div class="col-md-6">
				<h3><strong>{{sushi.quantity}}</strong></h3>
				<button class="btn btn-default pull-right" ng-show="purchase(sushi)">สั่งซื้อ</button>
				<button class="btn btn-default" ng-click="clickAdd(sushi)">Δ</button>
				<button class="btn btn-default" ng-click="clickRemove(sushi)">∇</button>
			</div>
		</div>
	</div>
</div>

ทำการเพิ่ม css class ชื่อ selected โดยมีรายละเอียดดังนี้

<head>
	....
	<style>.selected {color:white;background-color:red;}</style>
</head>
				

จากนั้น เพิ่ม ng-class ให้กับ list-group-item โดยมีเงื่อนไขคือผลที่ได้จาก store.purchase(sushi)

<div class="list-group" ng-controller="storeController as store" >
	<div class="list-group-item clearfix" ng-repeat="sushi in sushis" 
			ng-class="{'selected' : purchase(sushi)}">
		<h1>{{sushi.name}}
			<em class="pull-right">{{sushi.price | number:2}} yen</em>
		</h1>
		<div class="row">
			<div class="col-md-6"><img ng-src="{{sushi.image}}" /></div>
			<div class="col-md-6">
				<h3><strong>{{sushi.quantity}}</strong></h3>
				<button class="btn btn-default pull-right" ng-show="purchase(sushi)">สั่งซื้อ</button>
				<button class="btn btn-default" ng-click="clickAdd(sushi)">Δ</button>
				<button class="btn btn-default" ng-click="clickRemove(sushi)">∇</button>
			</div>
		</div>
	</div>
</div>

จะได้ผลลัพธ์ดังนี้ Demo

Challenge 7: Add Quantity

ทำการเพิ่ม จำนวน, ปุ่มเพิ่ม, ปุ่มลบ ให้กับซูชิแต่ละชิ้น

โดยมีโค้ดให้บางส่วน จงเติมส่วนที่ขาดหายไป เพื่อให้เว็บทำงานได้

สามารถดูผลลัพธ์ได้ที่ Demo

ไฟล์ sushistore.html

<!DOCTYPE html>
<html ng-app="application">
<head>
	<meta charset="utf-8">
    <!-- bootstrap CSS -->
    <link rel="stylesheet" href="css/bootstrap.min.css">
    <!-- bootstrap theme -->
    <link rel="stylesheet" href="css/bootstrap-theme.min.css">
</head>
<body>
	<header>
      <h1 class="text-center">{{"Tanaka" | uppercase}}{{"-San"}}'s Sushi Store</h1>
      <h2 class="text-center">Open Since {{10*200}}.</h2>
    </header>
    <div class="container">
        <div class="row">
            <div class="col-md-6">
				<div class="list-group" ng-controller="storeController as store" >
					<div class="list-group-item clearfix" ng-repeat="sushi in sushis">
						<h1>{{sushi.name}}
							<em class="pull-right">{{sushi.price | number:2}} yen</em>
						</h1>
						<div class="col-md-6"><img ng-src="{{sushi.image}}" /></div>
						<div class="col-md-6">
							<h3><strong></strong></h3>
							<button class="btn btn-default pull-right" ng-show="sushi.canPurchase">สั่งซื้อ</button>
							<button class="btn btn-default">Δ</button>
							<button class="btn btn-default">∇</button>
						</div>
					</div>
				</div>
            </div>
		</div>
	</div>
    <!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
    <script src="js/lib/jquery.min.js"></script>
    <!-- Bootstrap JavaScript -->
    <script src="js/lib/bootstrap.min.js"></script>
    <!-- AngularJS JavaScript -->
    <script src="js/lib/angular.min.js"></script>
    <script src="js/app.js"></script>
</body>
</html>

ไฟล์ app.js

(function () {
	'use strict';
	
	var app = angular.module('application', []);
	app.controller('storeController', function ($scope) {
		$scope.sushis = [
			{
				name: 'Maguro',
				price: 200,
				description: "Fat Tuna",
				quantity: 0,
				image: 'image/sushi/maguro.jpg'
			},
			{
				name: 'Tamago',
				price: 120,
				description: "Rice With Egg",
				quantity: 0,
				image: 'image/sushi/tamago.jpg'
			},
			{
				name: 'Ebi',
				price: 150,
				description: "Rice With shrimp",
				quantity: 0,
				image: 'image/sushi/ebi.jpg'
			},
			{
				name: 'Tako',
				price: 180,
				description: "Rice With Octopus",
				quantity: 0,
				image: 'image/sushi/tako.jpg'
			}
		];
		$scope.purchase = function (item) {};
		$scope.clickAdd = function (item) {};
		$scope.clickRemove = function (item) {};
	});
	
})();