Bootstrap7.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>

相关文章