Ajax7.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、Ajax显示路由于视图

里程由于政策,定义了为定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>

相关文章