โดยในหน้าจะประกอบด้วยส่วนของเมนูและส่วนของรายการที่สั่ง

ไฟล์ index.html ตั้งต้น

<div class="container">
	<div class="row" ui-view>

	</div>
</div>
  • สร้าง state ชื่อ sushi
  • ทำการดึงข้อมูล sushi จาก resolve โดยมีรายละเอียดดังนี้
    • {{item.name}} ราคา {{item.price}} yen
  • กำหนด templateUrl เป็น shop.html

    shop.html

    <div class="col-md-8">
    	<ul class="nav nav-pills navbar-default">
    		<li><a ui-sref="sushi">Sushi</a></li>
    	</ul>
    	<div>
    		<div class="list-group">
    			<div class="list-group-item row" ng-repeat="item in menuItem" ng-init="item.quantity = 0">
    				<h2 class="col-md-4">\{\{item.name}}</h2>
    				<div class="col-md-2"><em>\{\{item.price | number:2}} Yen </div>
    				<div class="col-md-2"><p>X \{\{item.quantity}}</p> <button class="btn btn-default" ng-click="increase(item)">increse</button>
    				<button class="btn btn-default" ng-click="decrease(item)">decrese</button></div>
    				<div class="col-md-2"><button class="btn btn-default pull-right" ng-click="orderCall(item)">+</button></div>
    			</div>
    		</div>
    	</div>
    	</div>
    	<div class="col-md-4">
    		<div class="list-group">
    			<div class="list-group-item row" ng-repeat="item in orderItem">
    				<h2 class="col-md-4">\{\{item.name}}</h2>
    				<div class="col-md-4"><em>\{\{item.price | number:2}} Yen </div>
    				<div class="col-md-2"><p>X \{\{item.quantity}}</p></div>
    				<div class="col-md-2"><button class="btn btn-default pull-right" ng-click="removeOrder(item)">X</button></div>
    			</div>
    			<button ng-show="orderItem.length > 0" ng-click="checkOut()" class="btn btn-danger col-md-12">Check Out</button>
    		</div>
    	</div>
    </div>		
    
  • กำหนด controller ให้มีรายละเอียดดังนี้
    controller: function ($scope, sushiItem) {
    	$scope.orderItem = [];
    	$scope.menuItem = sushiItem;
    	$scope.increase = function (item) { };
    	$scope.decrease = function (item) {	};
    	$scope.orderCall = function (item) { };
    	$scope.removeOrder = function (item) { };
    	$scope.checkOut = function () { };
    }
    

Answer of Checkpoint 1

angular.module('application', ['ui.router'])
    .config(function ($stateProvider, $urlRouterProvider) {
		$stateProvider
            .state('sushi', {
				url: '/sushi',
				resolve: {
					sushiItem: function () {
						var item = [
							{name: "Otaro", price: 200},
							{name: "Maguro", price: 300},
							{name: "Tamago", price: 120},
							{name: "Saba", price: 100},
							{name: "Tako", price: 150}
						];
						return item;
					}
				},
				templateUrl: 'shop.html',
				controller: function ($scope, sushiItem) {
					$scope.orderItem = [];
					$scope.menuItem = sushiItem;
					$scope.increase = function (item) { };
					$scope.decrease = function (item) {	};
					$scope.orderCall = function (item) { };
					$scope.removeOrder = function (item) { };
					$scope.checkOut = function () { };
				}
			});

จากรูปสังเกตได้ว่าในหน้านี้มีส่วนที่เหมือนกัน คือ [ส่วนของประเภทอาหาร]และ[ส่วนรายการที่สั่ง]

และส่วนที่ต่างกันคือ ข้อมูลใน [ส่วนของเมนูอาหาร]

เราจึงทำการสร้าง abstract state ชื่อว่า shop เป็น template ให้สามารถ reuse ส่วนต่างๆของ template ได้

โดยจะแบ่ง view ของเป็น 3 หน้าดังนี้

  • shop.html
    <div class="col-md-8">
    	<ul class="nav nav-pills navbar-default">
    		<li><a ui-sref="sushi">Sushi</a></li>
    		<li><a ui-sref="appetizer">Appetizer</a></li>
    		<li><a ui-sref="drink">Drink</a></li>
    	</ul><div ui-view="menulist"></div></div>
    	<div class="col-md-4" ui-view="order">
    	</div>
    </div>	
    
  • menu.html
    <div class="list-group">
    	<div class="list-group-item row" ng-repeat="item in menuItem" ng-init="item.quantity = 0">
    		<h2 class="col-md-4">\{\{item.name}}</h2>
    		<div class="col-md-2"><em>\{\{item.price | number:2}} Yen </div>
    		<div class="col-md-2"><p>X \{\{item.quantity}}</p> <button class="btn btn-default" ng-click="increase(item)">increse</button>
    		<button class="btn btn-default" ng-click="decrease(item)">decrese</button></div>
    		<div class="col-md-2"><button class="btn btn-default pull-right" ng-click="orderCall(item)">+</button></div>
    	</div>
    </div>
    
  • order.html
    <div class="list-group">
    	<div class="list-group-item row" ng-repeat="item in orderItem">
    		<h2 class="col-md-4">\{\{item.name}}</h2>
    		<div class="col-md-4"><em>\{\{item.price | number:2}} Yen </div>
    		<div class="col-md-2"><p>X \{\{item.quantity}}</p></div>
    		<div class="col-md-2"><button class="btn btn-default pull-right" ng-click="removeOrder(item)">X</button></div>
    	</div>
    	<button ng-show="orderItem.length > 0" ng-click="checkOut()" class="btn btn-danger col-md-12">Check Out</button>
    </div>
    

จากนั้นทำการสร้าง shop state ขึ้นมา โดย

  • กำหนดให้เป็น abstrct state
  • กำหนด templateUrl ไปที่ shop.html
  • ย้ายข้อมูลใน controller ของ sushi แยกออกมาดังนี้
    function ($scope, $state) {
    	$scope.orderItem = [];
    	$scope.increase = function (item) { };
    	$scope.decrease = function (item) {	};
    	$scope.orderCall = function (item) { };
    	$scope.removeOrder = function (item) { };
    	$scope.checkOut = function () { };
    }
    

เมื่อเราต้องการใช้ส่วนต่างๆของ shop state ก็ทำการกำหนดให้เป็น child state

กำหนด sushi state เป็น child state ของ shop

  • กำหนดให้ sushi เป็น child state ของ shop
  • กำหนด views แทนการใช้ templateUrl โดยมี 2 views ดังนี้
    • menulist
      • กำหนด templateUrl ไปที่ menu.html
      • กำหนด resolve ให้ดึงข้อมูล sushi มาแสดง
      • ใน controller ทำการกำหนดค่าให้กับ menuItem
    • order
      • กำหนดให้ templateUrl ไปที่ order.html

เพิ่ม appetizer state และ drink state โดยจะมีลักษณะ interface เหมือนกับ sushi

  • appetizer state จะมีข้อมูลที่ต้อง resolve ดังนี้
    • {{item.name}} ราคา {{item.price}} yen
  • drink state จะมีข้อมูลที่ต้อง resolve ดังนี้
    • {{item.name}} ราคา {{item.price}} yen

Answer of Checkpoint 2

angular.module('application', ['ui.router'])
    .config(function ($stateProvider, $urlRouterProvider) {
		$stateProvider
			.state('shop', {
				abstract: true
				templateUrl: 'shop.html',
				controller: function ($scope, sushiItem) {
					$scope.orderItem = [];
					$scope.menuItem = sushiItem;
					
					$scope.increase = function (item) { };
					$scope.decrease = function (item) {	};
					$scope.orderCall = function (item) { };
					$scope.removeOrder = function (item) { };
					$scope.checkOut = function () { };
				}
			})
            .state('shop.sushi', {
				url: '/sushi',
				resolve: {
					sushiItem: function () {
						var item = [
							{name: "Otaro", price: 200},
							{name: "Maguro", price: 300},
							{name: "Tamago", price: 120},
							{name: "Saba", price: 100},
							{name: "Tako", price: 150}
						];
						return item;
					}
				},
				views: {
					"menulist": {
						templateUrl: 'menu.html',
						controller: function ($scope, sushiItem) {
							$scope.menuItem = sushiItem;
						}
					},
					"order": {
						templateUrl: 'order.html'
					}
				}
			})
			.state('shop.appetizer', {
				url: '/appetizer',
				resolve: {
					sushiItem: function () {
						var item = [
							{name: "Takoyaki", price: 500},
							{name: "Okonomiyaki", price: 500},
							{name: "Yakisoba", price: 650},
							{name: "Soba", price: 400}
						];
						return item;
					}
				},
				views: {
					"menulist": {
						templateUrl: 'menu.html',
						controller: function ($scope, sushiItem) {
							$scope.menuItem = sushiItem;
						}
					},
					"order": {
						templateUrl: 'order.html'
					}
				}
			})
			.state('shop.drink', {
				url: '/drink',
				resolve: {
					sushiItem: function () {
						var item = [
							{name: "Coke", price: 100},
							{name: "Water", price: 100},
							{name: "Lemon Soda", price: 250},
							{name: "Matcha", price: 200}
						];
						return item;
					}
				},
				views: {
					"menulist": {
						templateUrl: 'menu.html',
						controller: function ($scope, sushiItem) {
							$scope.menuItem = sushiItem;
						}
					},
					"order": {
						templateUrl: 'order.html'
					}
				}
			});
  • increase(item) - เพิ่มจำนวนซูชิที่ต้องการ
  • decrease(item) - ลดจำนวนซูชิที่ต้องการ [hint: จำนวนไม่น้อยกว่า 0]
  • orderCall(item) - เพิ่มรายการที่สั่งลง orderItem [hint: push()]
  • removeOrder(item) - ลบรายการที่สั่งออกจาก orderItem [hint: splice()]

Answer of Checkpoint 3

angular.module('application', ['ui.router'])
    .config(function ($stateProvider, $urlRouterProvider) {
		$stateProvider
			.state('shop', {
				abstract: true
				templateUrl: 'shop.html',
				controller: function ($scope, sushiItem) {
					$scope.orderItem = [];
					$scope.menuItem = sushiItem;
					
					$scope.increase = function (item) {
						if (item.quantity !== null) {
							item.quantity += 1;
						}
					};
					$scope.decrease = function (item) {
						if (item.quantity !== null && item.quantity > 0) {
							item.quantity -= 1;
						}
					};
					$scope.orderCall = function (item) {
						if (item.quantity !== null && item.quantity > 0) {
							var addItem = angular.copy(item);
							$scope.orderItem.push(addItem);
							item.quantity = 0;
						}
					};
					$scope.removeOrder = function (item) {
						var index = $scope.orderItem.indexOf(item);
						$scope.orderItem.splice(index, 1);
					}
					$scope.checkOut = function () { };
				}
			})
            .state('shop.sushi', { ... })
			.state('shop.appetizer', { ... })
			.state('shop.drink', { ... });

สร้าง checkout state ขึ้นมา

  • กำหนด templateUrl เป็น checkout.html

    checkout.html

    <div>
    	<ul class="nav nav-pills navbar-default">
    		<li><a ui-sref="sushi">Back</a></li>
    	</ul>
    </div>
    <div class="list-group">
    	<div class="list-group-item row" ng-repeat="item in orderItem">
    		<h2 class="col-md-4">\{\{item.name}}</h2>
    		<div class="col-md-4">
    			<em>\{\{item.price | number:2}} Yen X \{\{item.quantity}} = \{\{item.quantity * item.price}} Yen
    		</div>
    	</div>
    	<div class="list-group-item row" >
    		<h2 class="col-md-4">Total</h2>
    		<h2 class="col-md-4">\{\{sum}} Yen</h2>
    	</div>
    	<button ng-click="payMoney()" class="btn btn-danger col-md-12">Pay</button>
    </div>
    
  • กำหนด params ให้รับค่า orderItem
    params: {'orderItem':''}						
    
  • กำหนดรายละเอียดของ controller ดังนี้
    function ($scope, $stateParams, $state) {
    	$scope.orderItem = $stateParams.orderItem;
    	$scope.sum = 0;
    	angular.forEach($scope.orderItem, function (item) {
    		$scope.sum += (item.price * item.quantity);
    	});
    	$scope.payMoney = function () {
    		alert("Thank you.");
    		$state.go('menu.sushi');
    	}
    }
    

แต่เรายังหาทางไปยัง checkout ไม่ได้ ฉะนั้นให้ทำการกำหนดฟังก์ชั่น checkOut() ใน shop state

  • กำหนดให้ map "orderItem" เข้ากับค่าของ orderItem ใส่ลงในตัวแปร params
  • ส่งค่า params ไปยัง checkout state

Answer of Checkpoint 4

angular.module('application', ['ui.router'])
    .config(function ($stateProvider, $urlRouterProvider) {
		$stateProvider
			.state('shop', {
				abstract: true
				templateUrl: 'shop.html',
				controller: function ($scope, sushiItem) {
					$scope.orderItem = [];
					$scope.menuItem = sushiItem;
					...
					$scope.checkOut = function () { 
						var params = {"orderItem":$scope.orderItem};
						$state.go("checkout", params);
					};
				}
			})
            .state('shop.sushi', { ... })
			.state('shop.appetizer', { ... })
			.state('shop.drink', { ... })
			.state('checkout', {
				url: '/checkout',
				params: {'orderItem':''},
				templateUrl: 'checkout.html',
				controller: function ($scope, $stateParams, $state) {
					$scope.orderItem = $stateParams.orderItem;
					$scope.sum = 0;
					angular.forEach($scope.orderItem, function (item) {
						$scope.sum += (item.price * item.quantity);
					});
					$scope.payMoney = function () {
						alert("Thank you.");
						$state.go('shop.sushi');
					}
				}
			});

สามารถดูผลลัพธ์ที่เสร็จแล้วได้ ที่นี่