《Pro AngularJS》该书以一个SportsStore案例为主线铺开。
一、开发环境设置
该书中所用的数据库data server开发环境是Deployed,从来没听说过,而且作者也说该数据库data server没什么人用,我干脆弃用之。其他的环境包括
我基本没学过NodeJS,只好使用了webstorm中的内置项目:Node.js Boilerplate来傻瓜化新建项目了。其启动NodeJS过程如下图(基本可按指示一步一步做⊙﹏⊙):
新建好项目后将所有文件放在static目录下,就先这样凑合着用了。我也暂时不使用数据库,直接使用JSON文件。
我的项目目录如下:
说明:
二、准备数据
我不熟悉NodeJS,使用一个Json文件作为数据源
[ { "name" : "Product #1", "description" : "A product", "category": "Category #1", "price": "100" }, { "name" : "Product #2", "description" : "A product", "category": "Category #1", "price": "110" }, { "name" : "Product #3", "description" : "A product", "category": "Category #2", "price": "210" }, { "name" : "Product #4", "description" : "A product", "category": "Category #3", "price": "202" }, { "name" : "Product #1", "description" : "A product", "category": "Category #1", "price": "100" }, { "name" : "Product #2", "description" : "A product", "category": "Category #1", "price": "110" }, { "name" : "Product #3", "description" : "A product", "category": "Category #2", "price": "210" }, { "name" : "Product #4", "description" : "A product", "category": "Category #3", "price": "202" } ]
创建sportsStore.js来引入并定义数据
angular.module("sportsStore") .controller("sportsStoreCtrl", function ($scope, $http) { $scope.data = {}; $http.get("products.json") .success(function(data){ $scope.data.products = data; }).error(function(error){ $scope.data.error = error; }); });
三、显示产品细节页面——直接上代码,即index.html
该代码主要用来显示产品的详细信息,即右边的面板panel的内容
<!DOCTYPE html> <html ng-app="sportsStore"> <!-- 标志AngularJs的开始 --> <head> <title>SportsStore</title> <script src="js/lib/angular.js"></script> <link href="css/bootstrap.css" rel="stylesheet" /> <link href="css/bootstrap-theme.css" rel="stylesheet" /> <script> angular.module("sportsStore", []); <!--加入sportsStore这个AngularJS应用 --> </script> <script src="js/controllers/sportsStore.js"></script> </head> <body ng-controller="sportsStoreCtrl"> <!-- 控制器sportStoreCtrl将应用于整个页面 --> <div class="navbar navbar-inverse"> <a class="navbar-brand" href="#">SPORTS STORE</a> </div> <div class="panel panel-default row"> <div class="col-xs-3 col-md-3">Categories go here</div> <div class="col-xs-8 col-md-8"> <div class="well" ng-repeat="item in data.products"> <h3> <strong>{{item.name}}</strong> <!--数据绑定 --> <span class="pull-right label label-primary"> {{item.price | currency}} <!-- currency filter将使该span的内容显示为货币格式 --> </span> </h3> <span class="lead">{{item.description}}</span> <!--数据绑定 --> </div> </div> </div> </body> </html>
四、定义左侧Category导航面板
1、加入的HTML
...
angular.module("sportsStore", ["customFilters"]); <!--加入customFilters模块 -->
...
<div class="panel panel-default row"> <div class="col-xs-3 col-md-3"> <a ng-click="selectCategory()" class="btn btn-block btn-default btn-lg">Home</a> <!--加入click事件 --> <a ng-repeat="item in data.products | orderBy:'category' | unique:'category'" <!--添加unique过滤,定义为按category属性过滤 --> ng-click="selectCategory(item)" class=" btn btn-block btn-default btn-lg"> <!--加入click事件 --> {{item}} </a> </div> ...... </div>
2. 新建customFilters.js——创建一个unique过滤,用来过滤Category
angular.module("customFilters", []) .filter("unique", function () { return function (data, propertyName) { if (angular.isArray(data) && angular.isString(propertyName)) { var results = []; var keys = {}; for (var i = 0; i < data.length; i++) { var val = data[i][propertyName]; if (angular.isUndefined(keys[val])) { //? keys[val] = true; results.push(val); } } return results; } else { return data; } } });
3. 新建productListControllers.js —— 实现按分类category显示产品信息(动态显示右边的面板内容)
angular.module("sportsStore") .controller("productListCtrl", function ($scope, $filter) { var selectedCategory = null; $scope.selectCategory = function (newCategory) { selectedCategory = newCategory; } $scope.categoryFilterFn = function (product) { return selectedCategory == null || product.category == selectedCategory; } });
注意:
4. 应用productListControllers和过滤产品——修改index.html
<divclass="panel panel-default row" ng-controller="productListCtrl"> <!--加入新的div层,使左右面板包含到该div,并加入productListCtrl --> <div class="col-xs-3 col-md-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"> {{item}} </a> </div> <div class="col-xs-8 col-md-8"> <div class="well" ng-repeat="item in data.products | filter:categoryFilterFn">
<!--加入categoryFilterFn,使得该div的内容随着右边面板的点击事件而变化--> <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> </div>
5. 高亮显示左边导航按钮(Highlighting the Selected Category)——使用
修改productListControllers.js
angular.module("sportsStore") .constant("productListActiveClass", "btn-primary") //使用constant方法定义一个常量productListActiveClass .controller("productListCtrl", function ($scope, $filter, productListActiveClass) {// var selectedCategory = null; $scope.selectCategory = function (newCategory) { selectedCategory = newCategory; } $scope.categoryFilterFn = function (product) { return selectedCategory == null || product.category == selectedCategory; } $scope.getCategoryClass = function(category) { return selectedCategory == category ? productListActiveClass : ""; } });
修改index.html中左边面板相关内容
... .controller("productListCtrl", function ($scope, $filter, productListActiveClass) { ... <div class="col-xs-3 col-md-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> ...
四、加入分页(pagination)
1. 修改productListControllers.js
angular.module("sportsStore") .constant("productListActiveClass", "btn-primary") .constant("productListPageCount", 3) //常量productlistPageCount,每页显示的产品数目 .controller("productListCtrl", function ($scope, $filter, productListActiveClass, productListPageCount) { var selectedCategory = null; $scope.selectedPage = 1; $scope.pageSize =