Статьи

Создание простой корзины покупок с помощью AngularJS: часть 2

В предыдущей части этого урока мы увидели, как начать создавать простую корзину с помощью AngularJS. Мы создали простой дизайн, но на самом деле не было достаточно AngularJS, чтобы назвать его AngularJS-приложением. В этой части серии руководств мы создадим пользовательскую директиву AngularJS для реализации необходимой функциональности.

Давайте начнем с клонирования исходного кода предыдущего урока из GitHub .

1
git clone https://github.com/jay3dec/AngularShoppingCart_Part1.git

После клонирования исходного кода перейдите в каталог проекта и установите необходимые зависимости.

1
2
cd AngularShoppingCart_Part1
npm install

Как только зависимости установлены, запустите сервер.

1
node server.js

Укажите в браузере http: // localhost: 3000 /, и приложение должно быть запущено.

На странице cart.html элементы и их параметры повторяются. Поэтому для этой цели мы создадим директиву AngularJS, которая будет создавать элементы и их параметры в соответствии с данными в серверной части. Для простоты рассмотрим следующие элементы в корзине:

01
02
03
04
05
06
07
08
09
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
[{
    ‘item’: ‘Hard Disk’,
    ‘id’: ‘HD’,
    ‘selected’: 0,
    ‘prices’: [{
        ‘size’: ‘200GB’,
        ‘price’: ‘2000’
    }, {
        ‘size’: ‘400GB’,
        ‘price’: ‘4000’
    }]
}, {
    ‘item’: ‘CPU’,
    ‘id’: ‘CPU’,
    ‘selected’: 0,
    ‘prices’: [{
        ‘size’: ‘i3’,
        ‘price’: ‘20000’
    }, {
        ‘size’: ‘i5’,
        ‘price’: ‘25000’
    }]
}, {
    ‘item’: ‘Monitor’,
    ‘id’: ‘MON’,
    ‘selected’: 0,
    ‘prices’: [{
        ‘size’: ’16\»,
        ‘price’: ‘3000’
    }, {
        ‘size’: ’19\»,
        ‘price’: ‘5000’
    }]
}, {
    ‘item’: ‘Optical Mouse’,
    ‘id’: ‘MOU’,
    ‘selected’: 0,
    ‘prices’: [{
        ‘size’: ‘Optical’,
        ‘price’: ‘350’
    }, {
        ‘size’: ‘Advanced’,
        ‘price’: ‘550’
    }]
}, {
    ‘item’: ‘RAM’,
    ‘id’: ‘RM’,
    ‘selected’: 0,
    ‘prices’: [{
        ‘size’: ‘4GB’,
        ‘price’: ‘4000’
    }, {
        ‘size’: ‘8GB’,
        ‘price’: ‘8000’
    }]
}, {
    ‘item’: ‘USB Keyboard’,
    ‘id’: ‘KEY’,
    ‘selected’: 0,
    ‘prices’: [{
        ‘size’: ‘Standard’,
        ‘price’: ‘2500’
    }, {
        ‘size’: ‘Advanced’,
        ‘price’: ‘4500’
    }]
}]

Добавьте следующие данные внутри CartCtrl .

01
02
03
04
05
06
07
08
09
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
$scope.shopData = [{
    ‘item’: ‘Hard Disk’,
    ‘id’: ‘HD’,
    ‘selected’: 0,
    ‘prices’: [{
        ‘size’: ‘200GB’,
        ‘price’: ‘2000’
    }, {
        ‘size’: ‘400GB’,
        ‘price’: ‘4000’
    }]
}, {
    ‘item’: ‘CPU’,
    ‘id’: ‘CPU’,
    ‘selected’: 0,
    ‘prices’: [{
        ‘size’: ‘i3’,
        ‘price’: ‘20000’
    }, {
        ‘size’: ‘i5’,
        ‘price’: ‘25000’
    }]
}, {
    ‘item’: ‘Monitor’,
    ‘id’: ‘MON’,
    ‘selected’: 0,
    ‘prices’: [{
        ‘size’: ’16\»,
        ‘price’: ‘3000’
    }, {
        ‘size’: ’19\»,
        ‘price’: ‘5000’
    }]
}, {
    ‘item’: ‘Optical Mouse’,
    ‘id’: ‘MOU’,
    ‘selected’: 0,
    ‘prices’: [{
        ‘size’: ‘Optical’,
        ‘price’: ‘350’
    }, {
        ‘size’: ‘Advanced’,
        ‘price’: ‘550’
    }]
}, {
    ‘item’: ‘RAM’,
    ‘id’: ‘RM’,
    ‘selected’: 0,
    ‘prices’: [{
        ‘size’: ‘4GB’,
        ‘price’: ‘4000’
    }, {
        ‘size’: ‘8GB’,
        ‘price’: ‘8000’
    }]
}, {
    ‘item’: ‘USB Keyboard’,
    ‘id’: ‘KEY’,
    ‘selected’: 0,
    ‘prices’: [{
        ‘size’: ‘Standard’,
        ‘price’: ‘2500’
    }, {
        ‘size’: ‘Advanced’,
        ‘price’: ‘4500’
    }]
}];

Удалите повторяющийся HTML-код cart.html из cart.html . Мы создадим HTML динамически, используя ngRepeat и $scope.shopData . Добавьте следующий HTML-код в первый столбец .row div.

1
2
3
4
5
6
7
8
<div class=»col-xs-7 col-md-8 col-sm-8 col-lg-8″>
    <div class=»panel panel-primary» ng-repeat=»q in shopData»>
        <div class=»panel-heading»>
            <h3 class=»panel-title»>{{q.item}}</h3>
        </div>
 
    </div>
</div>

Как видно из приведенного выше кода, используя ngRepeat мы итерировали по shopData и визуализировали HTML. Сохраните вышеуказанные изменения и перезагрузите сервер. Обновите страницу, и вы сможете просматривать элементы, отображаемые на странице.

Страница корзины с товарами

Далее мы покажем опцию, доступную вместе с конкретным элементом, таким как его размер и цена (см. Данные JSON). Для этого мы создадим нашу собственную директиву AngularJS. Директивы AngularJS являются одной из самых мощных функций AngularJS. Для получения подробной информации о директивах AngularJS, обратитесь к официальным документам .

Давайте создадим пользовательскую директиву с именем checkList . Откройте cart.js и создайте новую директиву, как показано:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
.directive(‘checkList’, function() {
    return {
        restrict: ‘E’,
        template: function(elem, attrs) {
            return ‘<div class=»panel-body»>\
                    <div class=»radio»>\
                        <label><input type=»radio»>Option1</label>\
                    </div>\
            <div class=»radio»>\
                        <label><input type=»radio»>Option2</label>\
                    </div>\
            <div class=»radio»>\
                        <label><input type=»radio»>Option2</label>\
                    </div>\
                </div>’
        }
    };
})

Эта директива имеет имя checkList . Директива checkList имеет два параметра: restrict и template . Restrict определяет, как будет вызываться директива. Поскольку мы определили E, оно будет называться именем элемента, например:

1
<check-list></check-list>

Поле template определило HTML-код, который заменит директиву checkList на странице. Мы использовали тот же статический HTML-код, что и раньше. Теперь вызовите директиву checkList на странице cart.html .

1
2
3
4
5
6
<div class=»panel panel-primary» ng-repeat=»q in shopData»>
    <div class=»panel-heading»>
        <h3 class=»panel-title»>{{q.item}}</h3>
    </div>
    <check-list></check-list>
</div>

Сохраните вышеуказанные изменения и обновите страницу корзины. Вы должны иметь возможность просматривать статические параметры HTML на странице корзины.

Страница корзины с директивой

Теперь давайте заставим директиву читать данные из $scope.shopData . Во-первых, вместо повторения параметров внутри директивы, мы будем использовать ngRepeat для итерации параметров. Измените директиву checkList как показано, чтобы сделать ее динамичной.

1
2
3
4
5
6
7
template: function(elem, attrs) {
    return ‘<div class=»panel-body»>\
                    <div class=»radio» ng-repeat=»i in option»>\
                        <label><input type=»radio»>{{i.size}} Rs.{{i.price}}</label>\
                    </div>\
                </div>’
}

Как видно из приведенного выше кода, мы ожидаем, что option будет передана в директиву. Таким образом, из части HTML мы должны определить атрибут для директивы checkList именем option и передать необходимые данные. Добавьте option в cart.html как показано:

1
2
3
4
5
6
<div class=»panel panel-primary» ng-repeat=»q in shopData»>
    <div class=»panel-heading»>
        <h3 class=»panel-title»>{{q.item}}</h3>
    </div>
    <check-list option=»q.prices»></check-list>
</div>

Чтобы получить доступ к переданному option внутри директивы, нам нужно определить область действия. Внутри директивы checkList определите scope как показано:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
.directive(‘checkList’, function() {
    return {
        restrict: ‘E’,
        scope: {
            option: ‘=’
        },
        template: function(elem, attrs) {
            return ‘<div class=»panel-body»>\
                    <div class=»radio» ng-repeat=»i in option»>\
                        <label><input type=»radio»>{{i.size}} Rs.{{i.price}}</label>\
                    </div>\
                </div>’
        }
    };
})

Таким образом, прайс-лист различных товаров из $scope.shopData передается в директиву. Сохраните вышеуказанные изменения и перезагрузите сервер. Обновите страницу, и вы сможете увидеть размер и цену каждого элемента в качестве параметров на странице.

Страница корзины с опциями, заполненными Dyancamilly

Теперь, если вы попытаетесь щелкнуть опцию переключателя для определенного элемента, оба будут выбраны. Чтобы гарантировать, что один элемент выбран одновременно, мы сгруппируем переключатели. Для этого нам потребуется передать еще один атрибут name в директиву из представления HTML. Поэтому добавьте новый атрибут name в check-list из представления. Мы передадим ID элемента в качестве name , поскольку он уникален для каждого элемента.

1
<check-list name=»q.id» option=»q.prices»></check-list>

Теперь добавьте еще одну переменную в область действия директивы, чтобы сделать ее доступной в шаблоне директивы.

1
2
3
4
scope: {
    option: ‘=’,
    name: ‘=’
}

Внутри template директивы HTML добавьте переданное имя в качестве имени переключателя, которое будет группировать переключатели определенных элементов.

1
<input type=»radio» name=»{{name}}»

Сохраните изменения и обновите страницу. Попробуйте выбрать переключатели для определенного элемента, и вы сможете выбрать только по одной за раз.

Основываясь на выбранных пользователем товарах, мы должны показать итоговую цену всех выбранных товаров. Для этого мы создадим функцию $scope которая называется total , которая будет суммировать итоговую цену. Каждый раз, когда пользователь выбирает элемент, мы обновляем переменную, выбранную в JSON $scope.shopData . Затем этот JSON повторяется, чтобы получить общую стоимость выбранных товаров. Вот total функция.

01
02
03
04
05
06
07
08
09
10
$scope.total = function() {
    var t = 0;
 
    for (var k in $scope.shopData) {
        t += parseInt($scope.shopData[k].selected);
    }
 
    return t;
 
}

Прямо сейчас мы показываем жестко закодированное значение 100 рупий в общем DIV. Вместо этого мы просто вызовем функцию total.

1
<h2>Rs.

Сохраните изменения и обновите страницу. Если вы попытаетесь выбрать разные варианты, общая сумма на самом деле не изменится. Это потому, что начальное значение selected переменной в JSON равно 0 и не обновляется при выделении. Итак, давайте передадим выбранное значение из JSON в директиву и обновим его, когда выбран переключатель. Измените представление HTML, чтобы включить еще один selected атрибут в checkList директивы checkList .

1
<check-list name=»q.id» selected=»q.selected» option=»q.prices»></check-list>

Добавьте selected в область действия директивы, чтобы получить доступ к ней внутри директивы.

1
2
3
4
5
scope: {
    option: ‘=’,
    name: ‘=’,
    selected: ‘=selected’
}

Мы установим selected в директиву ngModel а i.price в директиву ngValue . Следовательно, всякий раз, когда выбран переключатель, его значение обновляется в selected атрибуте JSON $scope.shopData .

1
<input type=»radio» ng-model=»$parent.selected» ng-value=»{{i.price}}» name=»{{name}}»>

Сохраните вышеуказанные изменения и обновите страницу. Попробуйте выбрать опции переключателя, и в зависимости от выбора, Total цена должна быть обновлена.

Страница корзины с итогом

В этой части серии руководств мы создали специальную директиву и использовали ее в нашем простом приложении для корзины покупок. В следующей части этой серии мы увидим, как сделать так, чтобы общий div всегда фиксировался сверху при прокрутке вниз. Также будет реализована страница оформления заказа, где будут отображаться выбранные товары и цены с кнопкой возврата на страницу корзины для настройки выбора.

Исходный код из этого урока доступен на GitHub . Дайте нам знать ваши мысли или любые исправления в комментариях ниже!