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

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

1
2
3
4
5
<div class="container">
    <div class="row" ui-view>
 
    </div>
</div>
  • สร้าง state ชื่อ sushi
  • ทำการดึงข้อมูล sushi จาก resolve โดยมีรายละเอียดดังนี้
    • Otaro ราคา 200 yen
    • Maguro ราคา 300 yen
    • Tamago ราคา 120 yen
    • Saba ราคา 100 yen
    • Tako ราคา 150 yen
  • กำหนด templateUrl เป็น shop.html

    shop.html

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    <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 ให้มีรายละเอียดดังนี้
    1
    2
    3
    4
    5
    6
    7
    8
    9
    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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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
    1
    2
    3
    4
    5
    6
    7
    8
    9
    <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
    1
    2
    3
    4
    5
    6
    7
    8
    9
    <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
    1
    2
    3
    4
    5
    6
    7
    8
    9
    <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 แยกออกมาดังนี้
    1
    2
    3
    4
    5
    6
    7
    8
    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 ดังนี้
    • Takoyaki ราคา 500 yen
    • Okonomiyaki ราคา 500 yen
    • Yakisoba ราคา 650 yen
    • Soba ราคา 400 yen
  • drink state จะมีข้อมูลที่ต้อง resolve ดังนี้
    • Coke ราคา 100 yen
    • Water ราคา 100 yen
    • Lemon Soda ราคา 250 yen
    • Matcha ราคา 200 yen

Answer of Checkpoint 2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <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
    1
    params: {'orderItem':''}                       
  • กำหนดรายละเอียดของ controller ดังนี้
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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');
                    }
                }
            });

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