7.1SportsStore:Navigation and Checkout

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

现在,要切换至用真实的数目,从Deployd服务器获取。

AngularJS通过一个称为$http的劳务,为Ajax请求提供支撑。作者用在第三有些详尽讲解它是怎工作的,在第23回讲解$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。一个Ajax请求是一个正式的HTTP请求以异步的法门发生,换句话说,在后台。AngularJS使用promises请求异步操作,这跟汝采取诸如jQeury这样的仓库很像(作者以第5章介绍,并当第20节解释)。

$http服务概念了不同之法子,来做不同类别之Ajax请求。Get方法,是作者这里用的,使用HTTP
GET方法,请求参数中之URL。作者就用URL定义为一个叫dataUrl的常量,并使第6回中测试了之Deployd服务器的URL。

$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时,显示。

提拔:作者将以第10章描述ng-show和ng-directives。

传递让error函数的对象,定义了status和message属性。状态属性设为HTTP error
code,message属性返回一个字符串,描述问题。作者以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>

提醒:使用一些视图有三独好处。第一个是打破用,使其更加好管理。第二,创建的HTML片段,可以用来采取中多次用。第三,使得为用户展示不同功能区域还爱。作者会以Defining
URL Routes 这等同省再说。

指令的创建器,可以指明它叫哪用:作为元素,作为性能,作为class,甚至作为HTML
评论。作者用于第16章讲。当AngularJS遇到ng-include指令,它做一个Ajax请求,加载src属性指定的文件,在拖欠因素位置,插入内容。展现让用户之始末看起没呀不同,但都略地装扮了app.html文件,将product列表相关的HTML都分手及一个文件被。

提拔:当以ng-include指令,在单引号中,指定文件的名。如果无如此做,那么指令会查找一个scope属性,来博文件之名。

  1. 创立购物车

用户可望可用的成品,但从没购物车,作者不能够销售其他东西。

若兑现购物车特点,许多组成部分用转变,包括要开创一个自定义的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为劳动提供一些功能,(只生一个对象会受创造,并被有因该服务之零件共享)。

连无是只有利用一个服务,才能够为咱演示AngularJS的基本点特征,但因这种办法实现购物车会很好,因为来一个共享的实例,确保其他组件能顾购物车,用户之出品选择生一致的视图。

作者将会以第18节解释,基于你而尝试的兑现,这里发生不同的法子创造服务。这里以Module.factory方法,传入服务之名字(本例中凡cart),和一个factory函数。当AngularJS需要劳务时,该factory函数会吃调用,创建服务目标,用以相应。因为一个劳务目标用于所有应用,factory函数只被调用一糟。

笔者的cart服务factory函数,返回一个目标,它起三个措施,操作一个不曾通过服务一直露出的数目数组,这是笔者用于演示的,你不用暴露服务之持有工作。该cart对象定义三独章程,介绍如下。作者在购物车中将产品表现吧目标,定义了id,name,price属性,来讲述产品,和一个count属性,记录用户添加入篮子的多少。

Method

Description

addProduct(id,name,price)

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

removeProduct(id)

使用指定id,移除产品

getProducts()

返回购物车中的对象数组

 

4.2、创建购物车部件

下同样步,要创一个部件,总结购物车的情节,提供被用户,意味着开始结账流程。下面,作者要创一个自定义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>

提醒:分布试图包含一个style元素,重定义Bootstrap
CSS的导航条之体裁。作者不连续好用style元素放在视图中,但他这么做了,因为这些样式就影响该待,并且独自是微量CSS。在所有其他情形下,作者又期望定义一个单身的CSS文件,导入到使用的主HTML文件中。

欠有的视图使用控制器的行为,来展示items的数据,和items的合计值。这里呢产生一个要素,叫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 组建,命名这些格式之间的映照,作者会在第15章节讲。

4.3、添加产品选择按钮

当有AngularJS开发,这里有许多预付的交付,来支付功能及另外特色,但是这些事物,如cart,都能以任何应用被选用。作者下同样步是被产品明细添加按钮,让用户可拿活丰富到买物车。第一,他得让控制器添加一个行事,让产品列表视图可以操作购物车。下面是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服务上声明了一个据,定义了一个名addProductToCart的所作所为,它具备一个成品对象,使用它们调用cart服务的addProduct方法。

提示:在服务达声称一个依,然后经scope选择性地展露其的职能,这种模式,在AngularJS开发被甚广泛。视图可以经过scope访问可用的行,但是笔者以第六段演示了,当控制器是嵌套的,或者当令给定义,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元素显示成相同之规范,为了方便,他赞同于交替地动用其。当以URL
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路由

作者要定义一个routes,在制定URL和苟显示的视图之间做映射。首先举行简单单照,/product和/chekcout
URLs,到成品列表页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方法的函数,在一个provider上宣称指。作者之前涉嫌,有两样的艺术可以创造AngularJS服务,一种就是由此安排provider对象来创造。作者在该provider上声明的一个依,是$routeProvider,用于在以中装置URL路由。

提示:作者以在第18章,解释如何利用providers创建服务,在第22段,解释如何行使$route服务和$routeProvider。

即时马上使$routeProvider对象定义之有数个模块,设置他要的路由。when方法允许作者以URL匹配到视图,象这样:

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

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

著。同样,也制定了一个怀有when方法还无匹配URL时,使用/views/ProductList.html视图文件,来对号入座。这听起象定义了一个fallback路由。

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

 

AngularJS不见面监视整个URL,因为形象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)

提拔:作者在第22节回道到,你可以HTML5 History
API,启用支持,改变URL的监视,使得象http://localhost:5000/checkout
这样的URL也能做事。当心,因为浏览器实现不同,当用户手工修改URL时,会招致浏览器尝试加载一个异之文档。

5.1.1、显示路由于视图

路途由于政策,定义了为定URL路径,要显的视图,但尚未报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、使用URL路由来导航

曾经定义了作者的URL路由,并下ng-view指令,作者可以变动URL路径,来导航应用。首先改变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元素添加了一个href属性,点击该因素,会招浏览器导航及新URL(它是固定及就加载了之文档)。该导航变化,会受AngularJS路由劳动意识,导致ng-view指令,显示checkoutSummary.html视图。

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

动用URL路由的特征是,该组建可在没有其它准备知识之时刻,通过ng-view指令来转布局。

6、开始结账流程

创造一个誉为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服务。它通过一个叫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>

相关文章