# 增加路由
> yo angular:route klass/index
```
panjiedeMacBook-Pro:app panjie$ yo angular:route klass/index
invoke angular:controller:/usr/local/lib/node_modules/generator-angular/route/index.js
create app/scripts/controllers/klass/index.js
create test/spec/controllers/klass/index.js
invoke angular:view:/usr/local/lib/node_modules/generator-angular/route/index.js
create app/views/klass/index.html
```
## V层
```
<input type="text" ng-model="name" />
<button type="button" ng-click="query()">确定</button>
<select ng-change="query()" ng-model="pageSize">
<option ng-value="2">2</option>
<option ng-value="3">3</option>
<option ng-value="4">4</option>
</select>
<table class="table">
<tr>
<th>序号</th>
<th>班级名称</th>
<th>辅导员</th>
<th>操作</th>
</tr>
<tr ng-repeat="(index, klass) in klasses">
<td>{{$index + 1}}</td>
<td>{{klass.name}}</td>
<td>{{klass.teacher.name}}</td>
<td></td>
</tr>
</table>
<nav class="text-center">
<ul class="pagination">
<li class="{{activeClass(1)}}">
<a ng-click="changePage(1)" href="javascript:void(0);">1</a>
</li>
<li class="{{activeClass(2)}}">
<a ng-click="changePage(2)" href="javascript:void(0);">2</a>
</li>
</ul>
</nav>
<div class="debug" ng-show="isDebug">
{{name}}
<br /> {{page}}
<br /> {{pageSize}}
<br /> {{klasses}}
</div>
```
## C层
```
'use strict';
/**
* @ngdoc function
* @name webAppApp.controller:KlassIndexCtrl
* @description
* # KlassIndexCtrl
* Controller of the webAppApp
*/
angular.module('webAppApp')
.controller('KlassIndexCtrl', function ($scope) {
// 初始化
var klasses = [];
$scope.page = 1; // 第几页
$scope.pageSize = 2; //每页大小
$scope.totalCount = 10; // 总条数
$scope.name = ''; // 查询条件
$scope.isDebug = true; // 开发环境
klasses.push({id:1, name:'一年级一班', teacher: {name: '王五'}});
klasses.push({id:2, name:'一年级二班', teacher: {name: '赵六'}});
klasses.push({id:3, name:'二年级一班', teacher: {name: '孙七'}});
$scope.klasses = klasses;
});
```
## 统一处理配置信息
我们在M层新建一个配置文件,存放项目的一些配置信息。这样,当项目上线时,只需要更改这一个配置文件就可以了。
比如我们在上面的V层中设置了:如果是开发环境,那么就显示下面的开发信息,否则就不显示。
> yo angular:constant config
config.js
```
'use strict';
/**
* @ngdoc service
* @name webAppApp.config
* @description
* # config
* Constant in the webAppApp.
*/
angular.module('webAppApp')
.constant('config', {
isDebug: false, // 开发模式
});
```
## 依赖注入
有了统一的配置文件,现在,我们将配置文件注入至klass/index.js
```
$scope.isDebug = config.isDebug; // 开发模式
```
## 动态处理分页
我们在V层中,对系统进行分页,但是静态分页。下面,我们更改为动态分页。
算法: 总页数 = 总条数 / 每页大小;
在此,我们使用ng-repeat结合我们自定义的filter来实现此功能。
### 改写为ng-repeat
V层:
```
<nav class="text-center">
<ul class="pagination">
<li ng-repeat="page in [1,2]" class="{{activeClass(page)}}">
<a ng-click="changePage(page)" href="javascript:void(0);">{{page}}</a>
</li>
</ul>
</nav>
```
在C层中,增加相应的方法:
```
// 为当前页增加active样式
var activeClass = function(index) {
if ($scope.page === index) {
return 'active';
} else {
return '';
}
};
// 用户点击分页触发
var changePage = function (index) {
$scope.page = index;
};
$scope.activeClass = activeClass;
$scope.changePage = changePage;
```
### 增加filter
```
panjiedeMacBook-Pro:WebApp panjie$ yo angular:filter paginationFilter
create app/scripts/filters/paginationfilter.js
create test/spec/filters/paginationfilter.js
```
paginationFilter.js
```
'use strict';
/**
* @ngdoc filter
* @name webAppApp.filter:paginationFilter
* @function
* @description
* # paginationFilter
* Filter in the webAppApp.
*/
angular.module('webAppApp')
.filter('paginationFilter', function() {
return function(items, pageSize, totalCount) {
// 计算共多少页
var page = totalCount / pageSize;
// 按页数大小push数组
for (var i = 1; i <= page; i++) {
items.push(i);
}
// 返回包含有分页的数组
return items;
};
});
```
### 单元测试
```
'use strict';
describe('Filter: paginationFilter', function() {
// load the filter's module
beforeEach(module('webAppApp'));
// initialize a new instance of the filter before each test
var paginationFilter;
beforeEach(inject(function($filter) {
paginationFilter = $filter('paginationFilter');
}));
it('每页2条,共10条,共5页', function() {
var items = [];
expect(paginationFilter(items, 2, 10).length).toBe(5);
});
it('每页1条,共10条,共10页', function() {
var items = [];
expect(paginationFilter(items, 1, 10).length).toBe(10);
});
it('每页2条,共11条,共6页', function() {
var items = [];
expect(paginationFilter(items, 2, 11).length).toBe(6);
});
```
由于前面,我们新C层时,没有进行单元测试。或是有单元测试已失效。可以将其单元测试的测试部分注释掉,以免对我们千万干扰。
测试结果:
```
PhantomJS 2.1.1 (Mac OS X 0.0.0) Filter: paginationFilter 每页2条,共11条,共6页 FAILED
Expected 5 to be 6.
test/spec/filters/paginationfilter.js:27:59
loaded@http://localhost:8081/context.js:151:17
```
提示我们最后一条记录没有通过,我们期待返回6,但实际上返回了5。这是由于,我们在计算时,没有进行上取整造成的。
### 修正BUG
增加Math.ceil函数,进行上取整处理。
```
// 计算共多少页
var page = Math.ceil(totalCount / pageSize);
```
上取整后,我们随便修改一下单元测试文件并保存,以使单元测试自动执行。测试通过。
## 将分页过滤器添加到前台
```
<li ng-repeat="page in [] | paginationFilter:pageSize:totalCount" class="{{activeClass(page)}}">
<a ng-click="changePage(page)" href="javascript:void(0);">{{page}}</a>
</li>
```
加入过滤器后,大体的执行过程是这样的:
1. 在进行ng-repeat以前,将`[]`和`pageSize`,`totalCount`传给过滤器.
![https://box.kancloud.cn/210214eee21229d5763a4882dbecc73d_2328x510.png](https://box.kancloud.cn/210214eee21229d5763a4882dbecc73d_2328x510.png)
2. 过滤器进行计算后,将我们计算后的值返回给`ng-repeat`
![https://box.kancloud.cn/ac90a1496fef78bbd7a91e8077ae2edc_2336x484.png](https://box.kancloud.cn/ac90a1496fef78bbd7a91e8077ae2edc_2336x484.png)
> 没错,过滤器,不但可以按我们的需求进行数据的修改,还可以去除一些我们认为不符合条件的,还可以呢去添加一些我们所需要的数据。
过滤器之所以能够在ng-repeat中过滤,是由于过滤器的优先级大于ng-repeat。
# 作业
1. 按上述方法,将 系统配置 注入至 教师管理 ,并按是否为开发模式,在前台显示测试信息。
2. 将serve.js中的URL前缀`http://127.0.0.1:8080/javaee`放到`config.js`中,并将`config`注入`server`以实现相同的功能。
> git checkout -f step12.1.1
- README
- 第一章:准备
- 第二章:Hello World!
- 第一节:查看工程文件
- 第二节:JDK、JRE与环境变量
- 第三节:index.jsp
- 第三章:Hello Struts
- 第一节:Web.xml
- 第二节:单入口
- 第三节:Hello Struts
- 第四节:触发C层
- 第四章:建立数据表
- 第一节:建立实体类
- 第二节:测试一
- 第三节:测试二
- 第四节:引入Hibernate
- 第五节:配置Hibernate
- 第六节:建立连接
- 第七节:实体类映射数据表
- 第八节:完善数据表
- 第五章:教师管理
- 第一节:增加数据--add
- 第二节:增加数据--save
- 1 获取传入数据数据
- 2 数据写入测试
- 3 对接C层
- 第三节:数据列表
- 1 获取数据
- 2 重构代码
- 3 C层对接--初始化
- 4 C层添加数据
- 5 V层显示数据
- 6 获取数据库中数据
- 7 显示性别
- 8 分页
- 9 条件查询
- 第四节:修改数据
- 1 edit
- 2 update
- 第五节:删除数据
- 第六节:总结
- 第六章:重构C层
- 第一节:继承ActionSupport类
- 第二节:数据验证
- 第七章:前台分离(前台)
- 第一节:环境搭建
- 第二节:运行环境
- 第三节:共享开发环境
- 第四节:生产环境
- 第八章:前台开发(前台)
- 第一节:本地化
- 第二节:教师列表
- 1 引入M层
- 2 模拟后台返回数据
- 3 C与M对接
- 4 C与V对接
- 第九章:前后台对接(前后台)
- 第一节:后台输出json(后台)
- 第二节:对接前台(全栈)
- 第二节:对接API(前台)
- 第二节:跨域请求(后台)
- 第三节:重构代码(前台)
- 第十章:重构后台M层
- 第一节:数据访问DAO层
- 第二节:项目整体重构
- 第十一章:用户登陆(前后台)
- 第一节:制定规范
- 第二节:定制测试用例
- 第三节:后台输入测试代码(后台)
- 第四节:postman(后台)
- 第五节:新建用户登陆模块(前台)
- 第六节:代码重构(前台)
- 第十二章:班级管理(前后台)
- 第一节:班级列表
- 1 原型开发
- 2 制定规范
- 3 后台对接开发
- 4 前台对接开发
- 第二节:Add
- 1 原型开发
- 2 制定规范
- 3 后台对接开发
- 4 前台对接开发
- 第三节:Save
- 1 制定规范
- 2 后台对接开发
- 3 前台对接开发
- 第四节:Edit
- 1 原型开发
- 2 制定规范
- 3 后台对接开发
- 4 前台对接开发
- 第五节:Update
- 1 制定规范
- 2 后台对接开发
- 3 前台对接开发
- 第六节:Delete
- 1 制定规范
- 2 后台对接开发
- 3 前台对接开发
- 第七节:小结
- 第十三章:班级管理(API)
- 第一节:ER图
- 第二节:create
- 1 实体层
- 2 dao层
- 3 service(server)层
- 4 action层
- 第三节:ManyToOne
- 第四节:Read
- 1 service(server)层
- 2 action层
- 第五节:update
- 1 service(server)层
- 2 action层
- 第六节:update
- 第十四章:重构服务层