7.1SportsStore:Navigation and Checkout

  1. 预备示例项目
  2. 使用真实的产品数据

昨日,要切换来使用真实的数额,从Deployd服务器获取。

AngularJS通过3个叫作$http的服务,为Ajax请求提供襄助。小编将在第2、局地详细讲解它是怎么工作的,在第三,3章讲解$http服务。未来有个简易的认识,修改顶尖控制器sportsStoreCtrl:

angular.module("sportsStore")

.constant("dataUrl", "http://localhost:5500/products")

.controller("sportsStoreCtrl", function ($scope, $http, dataUrl) {

$scope.data = {};

$http.get(dataUrl)

.success(function (data) {

$scope.data.products = data;

})

.error(function (error) {

$scope.data.error = error;

});

});

一大半JavaScript方法的调用,包蕴AngularJS组件里的措施,synchronous,意味着在当前职务完结前,不会履行下个评释。在web应用中,那就不可以办事,因为大家想让用户在呼吁在后台执行,用户可以持续和接纳交互。

作者运用Ajax请求获取须求的多寡。Ajax基于Asynchronous JavaScript and
XML,主要的是单词asynchronous。3个Ajax请求是三个业内的HTTP请求以异步的措施爆发,换句话说,在后台。AngularJS使用promises请求异步操作,那和您选拔像jQeury那样的库很像(小编在第陆章介绍,并在第三0章解释)。

$http服务概念了不相同的法门,来做不一致类其余Ajax请求。Get方法,是小编那里运用的,使用HTTP
GET方法,请求参数中的U汉兰达L。作者曾经将URubiconL定义为2个誉为dataUrl的常量,并使用第伍章中测试过的Deployd服务器的U奥迪Q5L。

$http.get方法,从Ajax请求开首,应用持续运营,直到请求已经终结。当服务器已经相应请求,AngularJS需求一种办法,来唤起用户,那就是promise的由来。该$http.get方法再次回到三个对象,定义success和error方法。笔者传递函数给这么些点子,AngularJS
promises调用那个函数中的三个,告诉我,请求是怎么结果。

如果HTTP请求的全套都运转很好,AngularJS会调用小编传递给success方法的函数,会自行转换JSON数据为Javascript对象,将他们当作参数传递给函数。若是Ajax
HTTP请求进度中有其余难点,AngularJS会调用小编传递给error方法的函数。

提示:JSON基于JavaScript Object
Notation,是一种数据交流格式,广泛地利用于web应用。

在success函数中,AngularJS会自动执行JSON数据的转移。我只需将从服务器获取的数目,指派给控制器scope的data.products变量。Error函数将对象指派给scope的data.error变量,来发挥难题。

2.1理解scope

当使用第肆遍开行,HTML内容被变型和出示给用户,尽管尚无产品消息可用。

在一个点过后,内容渲染落成,数据从服务器回来,指派给scope中的data.products变量。那时,AngularJS更新全数的绑定和计量尊崇于产品数据的作为的结果,确保新数据传播到使用的每一处。本质上,AngularJS
scope是 live
数据存储,响应和传唱改变。你会看出在本书中看看众多如此的例证。

2.2、处理Ajax错误

拍卖成功的Ajax请求很简短,因为只需将数据指派个scope,让AngularJS更新视图中颇具的绑定和下令。我不得不有个别困难地处理错误,添加一些新成分到视图,用于出现难点是展现出来。在上面可以旁观

<!DOCTYPE html>

<html ng-app="sportsStore">

<head>

<title>SportsStore</title>

<script src="angular.js"></script>

<link href="bootstrap.css" rel="stylesheet" />

<link href="bootstrap-theme.css" rel="stylesheet" />

<script>

angular.module("sportsStore", ["customFilters"]);

</script>

<script src="controllers/sportsStore.js"></script>

<script src="filters/customFilters.js"></script>

<script src="controllers/productListControllers.js"></script>

</head>

<body ng-controller="sportsStoreCtrl">

<div class="navbar navbar-inverse">

<a class="navbar-brand" href="#">SPORTS STORE</a>

</div>

<div class="alert alert-danger" ng-show="data.error">

Error ({{data.error.status}}). The product data was not loaded.

<a href="/app.html" class="alert-link">Click here to try again</a>

</div>

<div class="panel panel-default row" ng-controller="productListCtrl"

ng-hide="data.error">

<div class="col-xs-3">

<a ng-click="selectCategory()"

class="btn btn-block btn-default btn-lg">Home</a>

<a ng-repeat="item in data.products | orderBy:’category’ | unique:’category’"

ng-click="selectCategory(item)" class=" btn btn-block btn-default btn-lg"

ng-class="getCategoryClass(item)">

{{item}}

</a>

</div>

<div class="col-xs-8">

<div class="well"

ng-repeat=

"item in data.products | filter:categoryFilterFn | range:selectedPage:pageSize">

<h3>

<strong>{{item.name}}</strong>

<span class="pull-right label label-primary">

{{item.price | currency}}

</span>

</h3>

<span class="lead">{{item.description}}</span>

</div>

<div class="pull-right btn-group">

<a ng-repeat=

"page in data.products | filter:categoryFilterFn | pageCount:pageSize"

ng-click="selectPage($index + 1)" class="btn btn-default"

ng-class="getPageClass($index + 1)">

{{$index + 1}}

</a>

</div>

</div>

</div>

</body>

</html>

小编给视图添加了三个新的div成分,用于浮现错误给用户。使用ng-show指令,当表明式总括结果为true时,展现。

提醒:小编将在第9章描述ng-show和ng-directives。

传递给error函数的对象,定义了status和message属性。状态属性设为HTTP error
code,message属性再次来到3个字符串,描述难点。小编将status属性包括在message中显示给用户。

  1. 创办部分视图

App.html文件的HTML变得复杂了,今后添加新特色会很不好。

好在的是,小编可以分开文件,使用ng-include指令,在运维时来导入那几个文件。创设view/productList.html文件:

<div class="panel panel-default row" ng-controller="productListCtrl"

ng-hide="data.error">

<div class="col-xs-3">

<a ng-click="selectCategory()"

class="btn btn-block btn-default btn-lg">Home</a>

<a ng-repeat="item in data.products | orderBy:’category’ | unique:’category’"

ng-click="selectCategory(item)" class=" btn btn-block btn-default btn-lg"

ng-class="getCategoryClass(item)">

{{item}}

</a>

</div>

<div class="col-xs-8">

<div class="well"

ng-repeat=

"item in data.products | filter:categoryFilterFn | range:selectedPage:pageSize">

<h3>

<strong>{{item.name}}</strong>

<span class="pull-right label label-primary">

{{item.price | currency}}

</span>

</h3>

<span class="lead">{{item.description}}</span>

</div>

<div class="pull-right btn-group">

<a ng-repeat=

"page in data.products | filter:categoryFilterFn | pageCount:pageSize"

ng-click="selectPage($index + 1)" class="btn btn-default"

ng-class="getPageClass($index + 1)">

{{$index + 1}}

</a>

</div>

</div>

</div>

笔者将产品和归类列表的概念成分,拷贝到HTML文件。部分视图,是HTML的部分,意味着不需求html,head,body成分。

<!DOCTYPE html>

<html ng-app="sportsStore">

<head>

<title>SportsStore</title>

<script src="angular.js"></script>

<link href="bootstrap.css" rel="stylesheet" />

<link href="bootstrap-theme.css" rel="stylesheet" />

<script>

angular.module("sportsStore", ["customFilters"]);

</script>

<script src="controllers/sportsStore.js"></script>

<script src="filters/customFilters.js"></script>

<script src="controllers/productListControllers.js"></script>

</head>

<body ng-controller="sportsStoreCtrl">

<div class="navbar navbar-inverse">

<a class="navbar-brand" href="#">SPORTS STORE</a>

</div>

<div class="alert alert-danger" ng-show="data.error">

Error ({{data.error.status}}). The product data was not loaded.

<a href="/app.html" class="alert-link">Click here to try again</a>

</div>

<ng-include src="’views/productList.html’"></ng-include>

</body>

</html>

指示:使用一些视图有五个好处。第一个是打破应用,使其更为好管理。第3,成立的HTML片段,可以用来采用中屡屡重用。第一,使得为用户显示差异成效区域更便于。小编会在Defining
U卡宴L Routes 这一节再说。

命令的创设器,可以指明它被什么使用:作为成分,作为质量,作为class,甚至作为HTML
评论。小编将在第一6章解释。当AngularJS蒙受ng-include指令,它做三个Ajax请求,加载src属性指定的文件,在该因素地方,插入内容。突显给用户的始末看起来没有怎么差距,但已经简单地装扮了app.html文件,将product列表相关的HTML都分开到贰个文本中。

唤醒:当使用ng-include指令,在单引号中,指定文件的名字。即使没有如此做,那么指令会查找贰个scope属性,来博取文件的名字。

  1. 创造购物车

用户可以看出可用的制品,但未曾购物车,我无法销售其余东西。

要贯彻购物车特点,许多局地要求转变,包蕴要创造3个自定义的AngularJS组件。

4.1、定义购物腿模块和劳动

到此为止,都以透过文件的序列协会文件:过滤器包涵在过滤器文件夹,视图包罗在视图文件夹等等。但接二连三有部分效果,是自包括的,但须求混合AngularJS组件。你可以一而再用component类型社团文件,但作者找到了更实惠的不二法门,基于他们集体扮演的出力,来协会文件,放在components文件夹下。购物车成效适用于那种社团项目。作者须求不分时图和多少个组装件,来获取想要的效应。从创建components/cart文件夹起来,添加二个新的JavaScript文件叫做cart.js:

angular.module("cart", [])

.factory("cart", function () {

var cartData = [];

return {

addProduct: function (id, name, price) {

var addedToExistingItem = false;

for (var i = 0; i < cartData.length; i++) {

if (cartData[i].id == id) {

cartData[i].count++;

addedToExistingItem = true;

break;

}

}

if (!addedToExistingItem) {

cartData.push({

count: 1, id: id, price: price, name: name

});

}

},

removeProduct: function (id) {

for (var i = 0; i < cartData.length; i++) {

if (cartData[i].id == id) {

cartData.splice(i, 1);

break;

}

}

},

getProducts: function () {

return cartData;

}

}

});

笔者在称呼cart的新模块上穿件二个自定义服务。AngularJS为劳动提供部分效益,(唯有贰个目的会被创设,并被有着基于该服务的机件共享)。

并不是唯有应用3个劳动,才能为大家演示AngularJS的重中之重特点,但以那种措施达成购物车会很好,因为有一个共享的实例,确保其他组件能访问购物车,用户的产品选用有一致的视图。

我将会在第三8章解释,基于你要尝试的完成,那里有例外的法门开创服务。那里运用Module.factory方法,传入服务的名字(本例中是cart),和2个factory函数。当AngularJS必要劳务时,该factory函数会被调用,创造服务目的,用以相应。因为壹个劳动对象用于全部应用,factory函数只被调用一遍。

作者的cart服务factory函数,重临贰个对象,它有多个点子,操作一个从未经过劳动平昔露出的数码数组,这是作者用于演示的,你不要暴光服务的兼具工作。该cart对象定义多个措施,介绍如下。小编在购物车司令员产品表现为目标,定义了id,name,price属性,来描述产品,和贰个count属性,记录用户添出席篮子的数量。

Method

Description

addProduct(id,name,price)

添加指定产品到购物车,如果产品已经存在,增加该产品的需求数量

removeProduct(id)

使用指定id,移除产品

getProducts()

返回购物车中的对象数组

 

4.二,创制购物车部件

下一步,要开创一个部件,统计购物车的内容,提要求用户,意味着开始结账流程。上面,我要创造多少个自定义directive。Directives,是子包蕴,可选拔的成效的单元,它放在AngularJS开发的中坚地方。假如你用AngularJS,你会使用过多内建命令。单位了便宜,你会找到你协调创造的自定义命令,来让效果适合您的使用。

行使指令,你能做过多。它依然协助jQuery的删减版,叫jqLite,来操作DOM成分。简单来讲,命令允许你写任何事物,从简单的helpers,到复杂的表征,并操纵结果编织成当前的利用,或在此外使用中完全地采纳他们。上边是小编给cart.js文件中,创造widget
directive:

angular.module("cart", [])

.factory("cart", function () {

var cartData = [];

return {

// …service statements omitted for brevity…

}

})

.directive("cartSummary", function (cart) {

return {

restrict: "E",

templateUrl: "components/cart/cartSummary.html",

controller: function ($scope) {

var cartData = cart.getProducts();

$scope.total = function () {

var total = 0;

for (var i = 0; i < cartData.length; i++) {

total += (cartData[i].price * cartData[i].count);

}

return total;

}

$scope.itemCount = function () {

var total = 0;

for (var i = 0; i < cartData.length; i++) {

total += cartData[i].count;

}

return total;

}

}

};

});

经过在AngularJS模块上调用directive方法,创造指令,并传递指令的名字(本例中是cartSummary),和二个factory函数。该函数再次回到二个directive
definition
object。该指令定义对象定义了品质,会报告AngularJS,你的质量做哪些,怎么着做。当小编定义cartSumary指令时,定义了两个属性,上边简短地介绍他们。

Name

Description

Restrict

指定指令如何应用。作者使用E的值,意味着该指令只能作为一个元素应用。更公共的值是EA,意味着指令能作为一个元素或一个属性应用。

TemplateUrl

指定哪个URL的部分视图的内容,要插入到指令的元素
controller 制定一个控制器,给部分试图提供数据和行为

大约,作者的通令定义了多少个控制器,告诉AngularJS,使用components/cart/cartSummary.html视图,并限量指令,只好当作一个成分拔取。

<style>
.navbar-right { float: right !important; margin-right: 5px;}
.navbar-text { margin-right: 10px; }
</style>
<div class="navbar-right">
<div class="navbar-text">
<b>Your cart:</b>
{{itemCount()}} item(s),
{{total() | currency}}
</div>
<a class="btn btn-default navbar-btn">Checkout</a>
</div>

升迁:分布试图包罗1个style成分,重定义Bootstrap
CSS的导航条的样式。作者不一连喜欢将style成分放在视图中,但他那样做了,因为那些样式只影响该准备,并且只是微量CSS。在具有其余情况下,小编更愿意定义一个单身的CSS文件,导入到应用的主HTML文件中。

该有的视图使用控制器的一举一动,来显示items的数量,和items的合计值。那里也有2个因素,叫Checkout,点击该按钮,此刻还一贯不其他反应。

4.2.1、应用购物车部件

把购物车部件应用到应用,必要多少个步骤:添加script成分,倒入JavaScript文件的始末,添加对cart模块的借助,并充裕指令成分到markup。

<!DOCTYPE html>
<html ng-app="sportsStore">
<head>
<title>SportsStore</title>
<script src="angular.js"></script>
<link href="bootstrap.css" rel="stylesheet" />
<link href="bootstrap-theme.css" rel="stylesheet" />
<script>
angular.module("sportsStore", ["customFilters", "cart"]);
</script>
<script src="controllers/sportsStore.js"></script>
<script src="filters/customFilters.js"></script>
<script src="controllers/productListControllers.js"></script>
<script src="components/cart/cart.js"></script>
</head>
<body ng-controller="sportsStoreCtrl">
<div class="navbar navbar-inverse">
<a class="navbar-brand" href="#">SPORTS STORE</a>
<cart-summary />
</div>
<div class="alert alert-danger" ng-show="data.error">
Error ({{data.error.status}}). The product data was not loaded.
<a href="/app.html" class="alert-link">Click here to try again</a>
</div>
<ng-include src="'views/productList.html'"></ng-include>
</body>
</html>

小心小编运用cartSummary,定义指令,添加到app.html文件的成分,是cart-summary。AngularJS
normalizes 组建,命名那些格式之间的映照,我会在第叁,5章解释。

4.3、添加产品选取按钮

用作颇具AngularJS开发,那里有众多预支的付出,来支付功能和此外特色,可是这几个东西,如cart,都能在任何使用中引用。我下一步是给产品明细添加按钮,让用户可以把产品充分到购物车。第1他要求给控制器添加七个表现,让成品列表视图可以操作购物车。上边是controllers/productListController.js文件。

angular.module("sportsStore")
.constant("productListActiveClass", "btn-primary")
.constant("productListPageCount", 3)
.controller("productListCtrl", function ($scope, $filter,
productListActiveClass, productListPageCount, cart) {
var selectedCategory = null;
$scope.selectedPage = 1;
$scope.pageSize = productListPageCount;
$scope.selectCategory = function (newCategory) {
selectedCategory = newCategory;
$scope.selectedPage = 1;
}
$scope.selectPage = function (newPage) {
$scope.selectedPage = newPage;
}
$scope.categoryFilterFn = function (product) {
return selectedCategory == null ||
product.category == selectedCategory;
}

$scope.getCategoryClass = function (category) {
return selectedCategory == category ? productListActiveClass : "";
}
$scope.getPageClass = function (page) {
return $scope.selectedPage == page ? productListActiveClass : "";
}
$scope.addProductToCart = function (product) {
cart.addProduct(product.id, product.name, product.price);
}
});

小编在cart服务上表明了1个凭借,定义了2个称为addProductToCart的行事,它有着多个产品对象,使用它调用cart服务的addProduct方法。

指示:在劳动上声贝拉米(Bellamy)个依靠,然后通过scope拔取性地暴光它的功效,那种形式,在AngularJS开发中很广阔。视图可以透过scope访问可用的行为,不过笔者在第5章演示了,当控制器是嵌套的,大概当指令被定义,scopes可以继续另几个scope。

小编然后再产品明细的一部分视图上,添加按钮成分,调用addProductToCart行为。

<div class="panel panel-default row" ng-controller="productListCtrl"
ng-hide="data.error">
<div class="col-xs-3">
<a ng-click="selectCategory()"
class="btn btn-block btn-default btn-lg">Home</a>
<a ng-repeat="item in data.products | orderBy:'category' | unique:'category'"
ng-click="selectCategory(item)" class=" btn btn-block btn-default btn-lg"
ng-class="getCategoryClass(item)">
{{item}}
</a>
</div>
<div class="col-xs-8">
<div class="well"
ng-repeat=
"item in data.products | filter:categoryFilterFn | range:selectedPage:pageSize">
<h3>
<strong>{{item.name}}</strong>

{{item.price | currency}}

</h3>
<button ng-click="addProductToCart(item)"
class="btn btn-success pull-right">
Add to cart
</button>
{{item.description}}
</div>
<div class="pull-right btn-group">
<a ng-repeat=
"page in data.products | filter:categoryFilterFn | pageCount:pageSize"
ng-click="selectPage($index + 1)" class="btn btn-default"
ng-class="getPageClass($index + 1)">
{{$index + 1}}
</a>
</div>
</div>
</div>

提示:Bootstrap让作者可以将a和button元素突显成相同的规范,为了便于,他赞同于交替地采取它们。当使用U汉兰达L
routing时,a成分更有用。

 

5、添加URL导航

路由系统,可以让不相同部分准备,自动彰显。那使得构建大型应用越发简单。初阶,小编必要创建一个视图,当用户起首结账流程时,突显。放在views/checkoutSummary.html文件中。

<div class="lead">
This is the checkout summary view
</div>
<a href="#/products" class="btn btn-primary">Back</a>

 

5.1、定义URL路由

作者要定义1个routes,在制订U酷威L和要呈现的视图之间做映射。首先做七个映射,/product和/chekcout
U普拉多Ls,到成品列表页productList.html和checkoutSummary.html视图。

<!DOCTYPE html>
<html ng-app="sportsStore">
<head>
<title>SportsStore</title>
<script src="angular.js"></script>
<link href="bootstrap.css" rel="stylesheet" />
<link href="bootstrap-theme.css" rel="stylesheet" />
<script>
angular.module("sportsStore", ["customFilters", "cart", "ngRoute"])
.config(function ($routeProvider) {
$routeProvider.when("/checkout", {
templateUrl: "/views/checkoutSummary.html"
});
$routeProvider.when("/products", {
templateUrl: "/views/productList.html"
});
$routeProvider.otherwise({
templateUrl: "/views/productList.html"
});
});
</script>
<script src="controllers/sportsStore.js"></script>
<script src="filters/customFilters.js"></script>
<script src="controllers/productListControllers.js"></script>
<script src="components/cart/cart.js"></script>
<script src="ngmodules/angular-route.js"></script>
</head>
<body ng-controller="sportsStoreCtrl">
<div class="navbar navbar-inverse">
<a class="navbar-brand" href="#">SPORTS STORE</a>
<cart-summary />
</div>
<div class="alert alert-danger" ng-show="data.error">
Error ({{data.error.status}}). The product data was not loaded.
<a href="/app.html" class="alert-link">Click here to try again</a>
</div>
<ng-view />
</body>
</html>

小编将angular-route.js文件,导入到应用。该文件提供的听从,在贰个ngRoute的模块中,小编将它评释为sportsStore模块的借助。

要安装我的路由,他在模块对象上调用config方法。该格局将一个函数作为他的参数,当模块加载后,单运用还没被实施前,执行该函数。它提供为其它一次性地布局任务,提供机会。

笔者传递给config方法的函数,在1个provider上声称倚重。小编此前提到,有不相同的格局能够创设AngularJS服务,一种就是透过配备provider对象来创设。小编在该provider上表明的二个凭借,是$routeProvider,用于在运用中安装ULX570L路由。

唤醒:作者将在第贰8章,解释怎么样利用providers创制服务,在第12章,解释什么运用$route服务和$routeProvider。

那那使用$routeProvider对象定义的五个模块,设置他须要的路由。when方法允许小编将U卡宴L匹配到视图,象那样:

$routeProvider.when("/checkout", {
templateUrl: "/views/checkoutSummary.html"
});

该声明告诉AngularJS,当UCRUISERL是/checkout时,他想用/views/checkoutSummary.html文件

来得。同样,也制定了3个兼有when方法都不匹配U锐界L时,使用/views/ProductList.html视图文件,来对号入座。那听起来象定义了多少个fallback路由。

http://localhost:5000/app.html#/checkout

 

AngularJS不会监视整个UKugaL,因为象http://localhost:5000/checkout
那样的路由,会造成浏览器跳过AngularJS应用,尝试从服务器加载两个不等的文档。

URL Effect
http://localhost:5000/app.html#/checkout  Displays the
checkoutSummary.htmlview
http://localhost:5000/app.html#/products  Displays the
productList.htmlview
http://localhost:5000/app.html#/other Displays the
productList.htmlview (because of the
fallback route defined by the otherwisemethod)
http://localhost:5000/app.html  Displays the productList.htmlview
(because of the
fallback route defined by the otherwisemethod)

唤醒:小编在第叁,2章回讲到,你可以行使HTML5 History
API,启用援救,改变U奥迪Q5L的监视,使得象http://localhost:5000/checkout
那样的U牧马人L也能办事。当心,因为浏览器完成不一样,当用户手工修改U帕杰罗L时,会导致浏览器尝试加载多个不一的文档。

5.1.一,彰显路由视图

路由政策,定义了给定U中华VL路径,要呈现的视图,但尚未报告AngularJS,将他们加载到哪儿。小编要求利用ng-view指令,它在ngRoute模块中定义。使用ng-view替换ng-include。

<body ng-controller="sportsStoreCtrl">
<div class="navbar navbar-inverse">
<a class="navbar-brand" href="#">SPORTS STORE</a>
<cart-summary />
</div>
<div class="alert alert-danger" ng-show="data.error">
Error ({{data.error.status}}). The product data was not loaded.
<a href="/app.html" class="alert-link">Click here to try again</a>
</div>
<ng-view />
</body>

此处不须求安插选项和安装。只要求充足指令,告诉AngularJS,将日前甄选的视图的情节,插入到何地。

5.2、使用U景逸SUVL路由来导航

业已定义了我的U奥迪Q5L路由,并应用ng-view指令,笔者可以转移URAV4L路径,来导航应用。首先改变Checkout按钮。

<style>
.navbar-right { float: right !important; margin-right: 5px;}
.navbar-text { margin-right: 10px; }
</style>
<div class="navbar-right">
<div class="navbar-text">
<b>Your cart:</b>
{{itemCount()}} item(s),
{{total() | currency}}
</div>
<a href="#/checkout" class="btn btn-default navbar-btn">Checkout</a>
</div>

小编给a成分添加了3个href属性,点击该因素,会导致浏览器导航到新UMuranoL(它是永恒到曾经加载过的文档)。该导航变化,会被AngularJS路由服务意识,导致ng-view指令,呈现checkoutSummary.html视图。

专注点击checkout后,地址由http://localhost:5000/app.html
变为http://localhost:5000/app.html#/checkout,通过点击重回键,可以回退到上个视图。

行使U途锐L路由的天性是,该组建可以在并未此外准备知识的时候,通过ng-view指令来改变布局。

陆,开端结账流程

创造二个叫做cartSummaryController,

angular.module("sportsStore")
.controller("cartSummaryController", function($scope, cart) {
$scope.cartData = cart.getProducts();
$scope.total = function () {
var total = 0;
for (var i = 0; i < $scope.cartData.length; i++) {
total += ($scope.cartData[i].price * $scope.cartData[i].count);
}
return total;
}
$scope.remove = function (id) {
cart.removeProduct(id);
}
});

将新控制器添加到sportsStore模块,并凭借于cart服务。它通过3个称呼cartData的scope属性,曝露内容,定义了三个作为,总结购物车中产品的总价值,和从购物车中移除产品。

<h2>Your cart</h2>
<div ng-controller="cartSummaryController">
<div class="alert alert-warning" ng-show="cartData.length == 0">
There are no products in your shopping cart.
<a href="#/products" class="alert-link">Click here to return to the catalogue</a>
</div>
<div ng-hide="cartData.length == 0">
<table class="table">
<thead>
<tr>
<th>Quantity</th>
<th>Item</th>
<th class="text-right">Price</th>
<th class="text-right">Subtotal</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in cartData">
<td class="text-center">{{item.count}}</td>
<td class="text-left">{{item.name}}</td>
<td class="text-right">{{item.price | currency}}</td>
<td class="text-right">{{ (item.price * item.count) | currency}}</td>
<td>
<button ng-click="remove(item.id)"
class="btn btn-sm btn-warning">Remove</button>
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="3" class="text-right">Total:</td>
<td class="text-right">
{{total() | currency}}
</td>
</tr>
</tfoot>
</table>
<div class="text-center">
<a class="btn btn-primary" href="#/products">Continue shopping</a>
<a class="btn btn-primary" href="#/placeorder">Place order now</a>
</div>
</div>
</div>

此处没有新技巧。该控制器拔取ng-controller指令来制订,当购物车中绝非产品时,或有产品时,用ng-show和ng-hide指令来展现三个警戒。

 

6.壹,应用结账统计

下一步是添加1个script成分到app.html文件,并定义附加routes,用于已毕结账流程。

<!DOCTYPE html>
<html ng-app="sportsStore">
<head>
<title>SportsStore</title>
<script src="angular.js"></script>
<link href="bootstrap.css" rel="stylesheet" />
<link href="bootstrap-theme.css" rel="stylesheet" />
<script>
angular.module("sportsStore", ["customFilters", "cart", "ngRoute"])
.config(function ($routeProvider) {
$routeProvider.when("/complete", {
templateUrl: "/views/thankYou.html"
});
$routeProvider.when("/placeorder", {
templateUrl: "/views/placeOrder.html"
});
$routeProvider.when("/checkout", {
templateUrl: "/views/checkoutSummary.html"
});
$routeProvider.when("/products", {
templateUrl: "/views/productList.html"
});
$routeProvider.otherwise({
templateUrl: "/views/productList.html"
});
});
</script>
<script src="controllers/sportsStore.js"></script>
<script src="filters/customFilters.js"></script>
<script src="controllers/productListControllers.js"></script>
<script src="components/cart/cart.js"></script>
<script src="ngmodules/angular-route.js"></script>
<script src="controllers/checkoutControllers.js"></script>
</head>
<body ng-controller="sportsStoreCtrl">
<div class="navbar navbar-inverse">
<a class="navbar-brand" href="#">SPORTS STORE</a>
<cart-summary />
</div>
<div class="alert alert-danger" ng-show="data.error">
Error ({{data.error.status}}). The product data was not loaded.
<a href="/app.html" class="alert-link">Click here to try again</a>
</div>
<ng-view />
</body>
</html>

相关文章