课程目标
目标 1: 运用 AngularJS 前端框架的常用指令
目标 2: 完成品牌管理的列表功能
目标 3: 完成品牌管理的分页列表功能
目标 4: 完成品牌管理的增加功能
目标 5: 完成品牌管理的修改功能
目标 6: 完成品牌管理的删除功能
目标 7: 完成品牌管理的条件查询功能
-
1. 前端框架 AngularJS 入门
1.1 AngularJS 简介
AngularJS 诞生于 2009 年, 由 Misko Hevery 等人创建, 后为 Google 所收购. 是一款优秀的前端 JS 框架, 已经被用于 Google 的多款产品当中. AngularJS 有着诸多特性, 最为核心的是: MVC, 模块化, 自动化双向数据绑定, 依赖注入等等.
1.2 AngularJS 四大特征
1.2.1 MVC 模式
Angular 遵循软件工程的 MVC 模式, 并鼓励展现, 数据, 和逻辑组件之间的松耦合, 通过依赖注入(Dependency Injection),Angular 为客户端的 Web 应用带来了传统服务端的服务, 例如独立于视图的控制. 因此, 后端减少了许多负担, 产生了更轻的 Web 应用.
Model: 数据, 其实就是 angular 变量($scope.XX)
View: 数据的呈现, HTML+Directive(指令)
Controller: 操作数据, 就是 function, 数据的增删改查
1.2.2 双向绑定
AngularJS 是建立在这样的信念上的: 即声明式编程应该用于构建用户界面以及编写软件构建, 而指令式编程非常适合来表示业务逻辑. 框架采用并扩展了传统 HTML, 通过双向的数据绑定来适应动态内容, 双向的数据绑定允许模型和视图之间的自动同步. 因此, AngularJS 使得对 DOM 的操作不再重要并提升了可测试性.
1.2.3 依赖注入
依赖注入 (Dependency Injection, 简称 DI) 是一种设计模式, 指某个对象依赖的其他对象无需手工创建, 只需要 "吼一嗓子", 则此对象在创建时, 其依赖的对象由框架来自动创建并注入进来, 其实就是最少知识法则, 模块中所有的 service 和 provider 两类对象, 都可以根据形参名称实现 DI.
1.2.4 模块化设计
高内聚低耦合法则
1) 官方提供的模块 --- ng,ngRoute,ngAnimate
2) 用户自定义的模块 --- angular.module('模块名',[ ])
1.3 AngularJS 入门小 Demo
1.3.1 表达式指令
- <HTML>
- <head>
- <title>AngularJS 入门小 Demo-1 表达式指令</title>
- <script src="angular.min.js"></script>
- </head>
- <body ng-App>
- {{100+100}}
- </body>
- </HTML>
执行结果如下:
表达式的写法是{{表达式}} 表达式可以是变量或是运算式
ng-App 指令作用是告诉子元素指令是归 AngularJS 的, AngularJS 会识别的.
ng-App 指令定义了 AngularJS 应用程序的根元素.
ng-App 指令在网页加载完毕时会自动引导 (自动初始化) 应用程序.
1.3.2 双向绑定指令
- <HTML>
- <head>
- <title>AngularJS 入门小 Demo-2 双向绑定指令</title>
- <script src="angular.min.js"></script>
- </head>
- <body ng-App>
- 请输入你的姓名:<input ng-model="myname">
- <br>
- 请输入你的别名:<input ng-model="myname">
- <br>
{{myname}}, 你好!
</body>
</HTML>
运行效果如下:
ng-model 指令用于绑定变量, 这样用户在文本框输入的内容会绑定到变量上, 而表达式可以实时地输出变量.
1.3.3 初始化指令
我们如果希望有些变量具有初始值, 可以使用 ng-init 指令来对变量初始化.
- <HTML>
- <head>
- <title>AngularJS 入门小 Demo-3 初始化指令</title>
- <script src="angular.min.js"></script>
- </head>
- <body ng-App ng-init="myname='陈大海'">
- 请输入你的姓名:<input ng-model="myname">
- <br>
- 请输入你的别名:<input ng-model="myname">
- <br>
{{myname}}, 你好!
</body>
</HTML>
运行效果如下:
1.3.4 控制器指令
- <HTML>
- <head>
- <title>AngularJS 入门小 Demo-4 控制器指令</title>
- <script src="angular.min.js"></script>
- <script>
- var App=angular.module('myApp',[]); // 定义了一个名叫 myApp 的模块
- // 创建控制器
- App.controller('myController',function($scope){
- $scope.add=function(){
- return parseInt($scope.x) + parseInt($scope.y);
- }
- });
- </script>
- </head>
- <body ng-App="myApp" ng-controller="myController">
- x:<input ng-model="x">
- y:<input ng-model="y">
运算结果:{{add()}}
</body>
</HTML>
运行结果如下:
ng-controller 用于指定所使用的控制器.
理解 $scope:$scope 的使用贯穿整个 AngularJS App 应用, 它与数据模型相关联, 同时也是表达式执行的上下文. 有了 $scope 就在视图和控制器之间建立了一个通道, 基于作用域视图在修改数据时会立刻更新 $scope, 同样的 $scope 发生改变时也会立刻重新渲染视图.
1.3.5 事件指令
- <HTML>
- <head>
- <title>AngularJS 入门小 Demo-5 事件指令</title>
- <script src="angular.min.js"></script>
- <script>
- var App=angular.module('myApp',[]); // 定义了一个名叫 myApp 的模块
- // 创建控制器 $scope.z
- App.controller('myController',function($scope){
- $scope.add=function(){
- $scope.z = parseInt($scope.x) + parseInt($scope.y);
- }
- });
- </script>
- </head>
- <body ng-App="myApp" ng-controller="myController">
- x:<input ng-model="x">
- y:<input ng-model="y">
- <button ng-click="add()">运算</button>
结果:{{z}}
</body>
</HTML>
运行结果:
ng-click 是最常用的单击事件指令, 再点击时触发控制器的某个方法.
1.3.6 循环数组
- <HTML>
- <head>
- <title>AngularJS 入门小 Demo-6 循环数组</title>
- <script src="angular.min.js"></script>
- <script>
- var App=angular.module('myApp',[]); // 定义了一个名叫 myApp 的模块
- // 创建控制器 $scope.z
- App.controller('myController',function($scope){
- $scope.list= [100,192,203,434]; // 定义数组
- });
- </script>
- </head>
- <body ng-App="myApp" ng-controller="myController">
- <table>
- <tr ng-repeat="x in list">
- <td>{{x}}</td>
- </tr>
- </table>
- </body>
- </HTML>
运行结果如下:
这里的 ng-repeat 指令用于循环数组变量.
1.3.7 循环对象数组
- <HTML>
- <head>
- <title>AngularJS 入门小 Demo-7 循环对象数组</title>
- <script src="angular.min.js"></script>
- <script>
- var App=angular.module('myApp',[]); // 定义了一个名叫 myApp 的模块
- // 创建控制器 $scope.z
- App.controller('myController',function($scope){
- $scope.list= [
- {name:'张三',shuxue:99,yuwen:93},
- {name:'李四',shuxue:88,yuwen:87},
- {name:'王五',shuxue:77,yuwen:56}
- ]; // 定义数组
- });
- </script>
- </head>
- <body ng-App="myApp" ng-controller="myController">
- <table>
- <tr>
- <td > 姓名</td>
- <td > 数学</td>
- <td > 语文</td>
- </tr>
- <tr ng-repeat="entity in list">
- <td>{{entity.name}}</td>
- <td>{{entity.shuxue}}</td>
- <td>{{entity.yuwen}}</td>
- </tr>
- </table>
- </body>
- </HTML>
运行结果如下:
1.3.8 内置服务
我们的数据一般都是从后端获取的, 那么如何获取数据呢? 我们一般使用内置服务 $http 来实现. 注意: 以下代码需要在 tomcat 中运行.
- <!DOCTYPE HTML>
- <HTML>
- <head>
- <meta charset="UTF-8">
- <title>
- AngularJS 入门小 Demo-8 内置服务
- </title>
- <script src="angular.min.js">
- </script>
- <script>
- var App = angular.module('myApp', []); // 定义了一个名叫 myApp 的模块
- // 定义控制器
- App.controller('myController',
- function($scope, $http) {
- $scope.findAll = function() {
- $http.get('data.json').success(function(response) {
- $scope.list = response;
- });
- }
- });
- </script>
- </head>
- <body ng-App="myApp" ng-controller="myController" ng-init="findAll()">
- <table>
- <tr>
- <td>
- 姓名
- </td>
- <td>
- 数学
- </td>
- <td>
- 语文
- </td>
- </tr>
- <tr ng-repeat="entity in list">
- <td>
- {{entity.name}}
- </td>
- <td>
- {{entity.shuxue}}
- </td>
- <td>
- {{entity.yuwen}}
- </td>
- </tr>
- </table>
- </body>
- </HTML>
建立文件 data.JSON, 注意 JSON 文件格式, key 必须有双引号, 末尾没有逗号.
- [
- {"name":"张三","shuxue":99,"yuwen":93},
- {"name":"李四","shuxue":88,"yuwen":87},
- {"name":"王五","shuxue":77,"yuwen":56},
- {"name":"赵六","shuxue":59,"yuwen":70}
- ]
运行结果如下:
2. 品牌列表的实现
2.1 需求分析
实现品牌列表的查询 (不用分页和条件查询) 效果如下:
2.2 前端代码
2.2.1 拷贝页面资源
将 "资源 / 静态原型 / 运营商管理后台" 下的页面资源拷贝到 pinyougou-manager-Web 下:
其中 plugins 文件夹中包括了 AngularJS,Bootstrap,jQuery 等常用前端库, 我们将在项目中用到.
2.2.2 引入 JS
修改 brand.HTML , 引入 JS
- <!-- 引入 angularjs 文件 -->
- <script type="text/javascript" src="../plugins/angularjs/angular.min.js">
- </script>
2.2.3 指定模块和控制器
<body class="hold-transition skin-red sidebar-mini" ng-App="pinyougou" ng-controller="brandController">
ng-App 指令中定义的就是模块的名称.
ng-controller 指令用于为你的应用添加的控制器.
在控制器中, 你可以编写代码, 制作函数和变量, 并使用 scope 对象来访问.
2.2.4 编写 JS 代码
- <script type="text/javascript">
- var App=angular.module('pinyougou',[]); // 定义品优购模块
- App.controller('brandController',function($scope,$http){ // 定义控制器
- // 读取品牌列表数据绑定到表单中
- $scope.finAll=function(){
- $http.get('../brand/findAll.do').success(
- function(response){
- $scope.list=response;
- }
- );
- }
- });
- </script>
2.2.5 循环显示表格数据
- <!-- 数据列表 -->
- <table id="dataList" class="table table-bordered table-striped table-hover dataTable">
- <thead>
- <tr>
- <th class=""style="padding-right:0px">
- <input id="selall" type="checkbox" class="icheckbox_square-blue">
- </th>
- <th class="sorting_asc">品牌 ID</th>
- <th class="sorting">品牌名称</th>
- <th class="sorting">品牌首字母</th>
- <th class="text-center">操作</th>
- </tr>
- </thead>
- <tbody>
- <tr ng-repeat="entity in list">
- <td><input type="checkbox"></td>
- <td>{{entity.id}}</td>
- <td>{{entity.name}}</td>
- <td>{{entity.firstChar}}</td>
- <td class="text-center">
- <button type="button" class="btn bg-olive btn-xs" data-toggle="modal" data-target="#editModal">修改</button>
- </td>
- </tr>
- </tbody>
- </table>
2.2.6 初始化调用
<body class="hold-transition skin-red sidebar-mini" ng-App="pinyougou" ng-controller="brandController" ng-init="findAll()">
3. 品牌列表分页的实现
3.1 需求分析
在品牌管理下方放置分页栏, 实现品牌分页功能
3.2 后端代码
后端给前端的数据有:
1)total: 总记录数.
2)rows: 当前页记录的集合.
JSON 数据格式:{"total":100,"rows":[{"id":1,"name":"张三"},{"id":2,"name":"李四"}]}
方法一: 在后端将查询到的数据封装成 Map 集合
- Map map = new HashMap();
- map.put("total",1000);
- map.put("rows",list);
- return map;
fastjson 会自动转换 Map 集合数据.
方法二: 创建分页查询时返回的结果类 (包装类) 来进行接收, 该类包含 total 和 rows 属性.
3.2.1 将从数据库查询的分页结果封装实体
在 pinyougou-pojo 工程中创建 entity 包, 用于存放通用实体类, 创建类 PageResult
- package entity;
- import java.io.Serializable;
- import java.util.List;
- /**
- * 数据库分页查询时返回的结果类(包装类)
- * @author chenmingjun
- * @date 2019 年 1 月 14 日
- */
- public class PageResult implements Serializable {
- private Long total; // 总记录数
- private List<?> rows; // 当前页记录的集合
- private static final long serialVersionUID = 1L;
- public PageResult() {
- super();
- }
- public PageResult(Long total, List<?> rows) {
- super();
- this.total = total;
- this.rows = rows;
- }
- public Long getTotal() {
- return total;
- }
- public void setTotal(Long total) {
- this.total = total;
- }
- public List<?> getRows() {
- return rows;
- }
- public void setRows(List<?> rows) {
- this.rows = rows;
- }
- @Override
- public String toString() {
- return "EasyUIDataGridResult [total=" + total + ", rows=" + rows + "]";
- }
- }
3.2.2 服务接口层
在 pinyougou-sellergoods-interface 的 BrandService.java 增加方法定义
- /**
- * 分页查询全部品牌列表
- * @param pageNum 当前页的页码
- * @param pageSize 每页要显示的记录数
- * @return PageResult
- */
- PageResult findPage(Integer pageNum, Integer pageSize);
3.2.3 服务实现层
在 pinyougou-sellergoods-service 的 BrandServiceImpl.java 中实现该方法
- @Override
- public PageResult findPage(Integer pageNum, Integer pageSize) {
- // 设置分页信息, 使用 PageHelper 分页插件
- PageHelper.startPage(pageNum, pageSize);
- // 执行查询, 不需要设置查询条件, 即查询所有
- TbBrandExample example = new TbBrandExample();
- List<TbBrand> list = brandMapper.selectByExample(example);
- // 取出分页信息, 分页后, 实际返回的结果 list 类型是 Page<E>, 如果想取出分页信息
- // 方式一: 需要强制转换为 Page<E > 后, 使用 Page 对象进行处理
- // Page<TbBrand> page = (Page<TbBrand>) list;
- // return new PageResult(page.getTotal(), page.getResult());
- // 方式二: 我们使用 PageInfo 对象对查询出来的结果进行包装, 由于 PageInfo 中包含了非常全面的分页属性, 推荐使用方式二
- PageInfo<TbBrand> pageInfo = new PageInfo<>(list);
- // 创建分页查询时返回的结果类对象
- PageResult result = new PageResult();
- // 给返回的查询结果对象设置值(即封装数据)
- result.setTotal(pageInfo.getTotal());
- result.setRows(list);
- return result;
- }
PageHelper 为 MyBatis 分页插件.
3.2.4 控制层
在 pinyougou-manager-Web 工程的 BrandController.java 新增方法
- @RequestMapping("/findPage")
- public PageResult findPage(int page, int rows) {
- PageResult result = brandService.findPage(page, rows);
- return result;
- }
3.3 前端代码
前端给后端的数据有:
1)page: 当前页的页码, 从 1 开始.
2)rows: 每页要显示的记录数.
注意: 此处的 rows 与上处的 rows 的含义区别.
3.3.1 HTML
在 brand.HTML 引入分页组件
- <!-- 分页组件开始 -->
- <link rel="stylesheet" href="../plugins/angularjs/pagination.css">
- <script src="../plugins/angularjs/pagination.js"></script>
- <!-- 分页组件结束 -->
引入分页模块
var App=angular.module('pinyougou',['pagination']); // 定义品优购模块, 引入分页模块
页面的表格下放置分页控件
- <!-- 分页控件 -->
- <tm-pagination conf="paginationConf"></tm-pagination>
3.3.2 JS 代码
在控制器 brandController 中添加如下代码
- // 分页控件初始化配置
- $scope.paginationConf={
- currentPage: 1, // currentPage: 当前页 (初始化)
- totalItems: 10, // totalItems: 总记录数(初始化)
- itemsPerPage: 10, // itemsPerPage: 每页记录数(初始化)
- perPageOptions: [10, 20, 30, 40, 50], // perPageOptions: 分页选项(初始化)
- onChange: function(){ // onChange: 当页码变更后自动触发的方法
- $scope.reloadList();
- }
- };
- // 刷新列表方法
- $scope.reloadList=function(){
- $scope.findPage($scope.paginationConf.currentPage,$scope.paginationConf.itemsPerPage);
- }
- // 分页方法, 作用是请求后端数据
- $scope.findPage=function(page,rows){ // 方法名 findPage 可以自定义
- $http.get('../brand/findPage.do?page='+page+'&rows='+rows).success(
- function(response){ // 注意: 请求参数中的 rows 与响应数据的 rows 的区别
- $scope.list=response.rows; // 显示当前页数据
- $scope.paginationConf.totalItems=response.total; // 更新总记录数
- }
- );
- }
在页面的 body 元素上去掉 ng-init 指令的调用.
4. 增加品牌
4.1 需求分析
实现品牌增加功能
4.2 后端代码
4.2.1 服务接口层
在 pinyougou-sellergoods-interface 的 BrandService.java 新增方法定义
- /**
- * 增加品牌
- * @param brand
- */
- void add(TbBrand brand);
4.2.2 服务实现层
在 com.pinyougou.sellergoods.service.impl 的 BrandServiceImpl.java 实现该方法
- @Override
- public void add(TbBrand brand) {
- // 判断品牌名称是否重复: 方法一: 代码逻辑上判断, 如下; 方法二: 数据库设置品牌表的 name 属性为唯一约束
- TbBrandExample example = new TbBrandExample();
- Criteria criteria = example.createCriteria();
- criteria.andNameEqualTo(brand.getName());
- List<TbBrand> list = brandMapper.selectByExample(example);
- // 判断查询结果
- if (list == null || list.size() == 0) {
- // 品牌不存在, 则新增品牌
- brandMapper.insert(brand);
- } else {
- // 品牌已存在, 则抛出自定义异常信息 "品牌已存在"
- }
- }
4.2.3 将控制层执行的结果封装实体
在 pinyougou-pojo 的 entity 包下创建类 Result.java
- /**
- * 自定义的返回结果
- * @author chenmingjun
- * @date 2019 年 1 月 15 日
- */
- public class Result implements Serializable{
- private static final long serialVersionUID = 1L;
- private Boolean success; // 是否成功
- private String message; // 返回信息
- public Result(Boolean success, String message) {
- super();
- this.success = success;
- this.message = message;
- }
- public Boolean getSuccess() {
- return success;
- }
- public void setSuccess(Boolean success) {
- this.success = success;
- }
- public String getMessage() {
- return message;
- }
- public void setMessage(String message) {
- this.message = message;
- }
- @Override
- public String toString() {
- return "Result [success=" + success + ", message=" + message + "]";
- }
- }
4.2.4 控制层
在 pinyougou-manager-Web 的 BrandController.java 中新增方法
- @RequestMapping("/add")
- public Result add(@RequestBody TbBrand brand){
- try {
- brandService.add(brand);
- return new Result(true, "增加品牌成功");
- } catch (Exception e) {
- e.printStackTrace();
- return new Result(false, "增加品牌失败");
- }
- }
4.3 前端代码
4.3.1 JS 代码
- // 新增品牌方法
- $scope.save=function(){
- $http.post('../brand/add.do',$scope.entity).success(
- function(response){
- if(response.success){
- $scope.reloadList(); // 刷新列表方法
- }else{
- alert(response.message);
- }
- }
- );
- }
- 4.3.2 HTML
绑定表单元素, 我们用 ng-model 指令, 绑定按钮的单击事件我们用 ng-click 指令
- <div class="modal-content">
- <div class="modal-header">
- <button type="button" class="close" data-dismiss="modal" aria-hidden="true">*</button>
- <h3 id="myModalLabel">品牌编辑</h3>
- </div>
- <div class="modal-body">
- <table class="table table-bordered table-striped" width="800px">
- <tr>
- <td > 品牌名称</td>
- <td><input class="form-control" placeholder="品牌名称" ng-model="entity.name"></td>
- </tr>
- <tr>
- <td > 首字母</td>
- <td><input class="form-control" placeholder="首字母" ng-model="entity.firstChar"></td>
- </tr>
- </table>
- </div>
- <div class="modal-footer">
- <button class="btn btn-success" data-dismiss="modal" aria-hidden="true" ng-click="save()">保存</button>
- <button class="btn btn-default" data-dismiss="modal" aria-hidden="true">关闭</button>
- </div>
- </div>
为了每次打开窗口没有遗留上次的数据, 我们可以修改新建按钮, 对 entity 变量进行清空操作
- <button type="button" class="btn btn-default" title="新建" data-toggle="modal" data-target="#editModal" ng-click="entity={}">
- <i class="fa fa-file-o"></i> 新建
- </button>
5. 修改品牌
5.1 需求分析
点击列表的修改按钮, 弹出窗口, 修改数据后点 "保存" 执行保存操作
5.2 后端代码
5.2.1 服务接口层
在 pinyougou-sellergoods-interface 的 BrandService.java 新增方法定义
- /**
- * 根据品牌 ID 查询品牌实体
- * @param id
- * @return
- */
- TbBrand findOne(Long id);
- /**
- * 修改 (更新) 品牌
- * @param brand
- */
- void update(TbBrand brand);
5.2.2 服务实现层
在 pinyougou-sellergoods-service 的 BrandServiceImpl.java 新增方法实现
- @Override
- public TbBrand findOne(Long id) {
- TbBrand brand = brandMapper.selectByPrimaryKey(id);
- return brand;
- }
- @Override
- public void update(TbBrand brand) {
- brandMapper.updateByPrimaryKey(brand);
- }
5.2.3 控制层
在 pinyougou-manager-Web 的 BrandController.java 新增方法
- @RequestMapping("/findOne")
- public TbBrand findOne(Long id) {
- TbBrand brand = brandService.findOne(id);
- return brand;
- }
- @RequestMapping("/update")
- public Result update(@RequestBody TbBrand brand){
- try {
- brandService.update(brand);
- return new Result(true, "修改品牌成功");
- } catch (Exception e) {
- e.printStackTrace();
- return new Result(false, "修改品牌失败");
- }
- }
5.3 前端代码
5.3.1 实现数据查询
增加 JS 代码
- // 根据品牌 ID 查找某一个品牌实体方法, 用于回显数据
- $scope.findOne=function(id){
- $http.get('../brand/findOne.do?id='+id).success(
- function(response){
- $scope.entity=response;
- }
- );
- }
修改列表中的 "修改" 按钮, 调用此方法执行查询实体的操作
- <td class="text-center">
- <button type="button" class="btn bg-olive btn-xs" data-toggle="modal" data-target="#editModal" ng-click="findOne(entity.id)">修改</button>
- </td>
5.3.2 保存数据
修改 JS 的 save 方法
- // 新增 / 修改品牌方法
- $scope.save=function(){
- // 方式一: 可以在前端判断是新增方法还是修改方法, 方式二: 可以在后端判断是新增方法还是修改方法
- var methodName='add';
- if($scope.entity.id!=null){ // 如果有 ID
- methodName='update'; // 则执行修改方法
- }
- $http.post('../brand/'+methodName+'.do',$scope.entity).success(
- function(response){
- if(response.success){
- $scope.reloadList(); // 刷新列表方法
- }else{
- alert(response.message);
- }
- }
- );
- }
6. 删除品牌
6.1 需求分析
点击列表前的复选框, 点击删除按钮, 删除选中的品牌.
6.2 后端代码
6.2.1 服务接口层
在 pinyougou-sellergoods-interface 的 BrandService.java 接口定义方法
- /**
- * 根据品牌 ID 批量删除品牌
- * @param ids
- */
- void delete(Long[] ids);
6.2.2 服务实现层
在 pinyougou-sellergoods-service 的 BrandServiceImpl.java 实现该方法
- @Override
- public void delete(Long[] ids) {
- for (Long id : ids) {
- brandMapper.deleteByPrimaryKey(id);
- }
- }
6.2.3 控制层
在 pinyougou-manager-Web 的 BrandController.java 中增加方法
- @RequestMapping("/delete")
- public Result delete(Long[] ids) {
- try {
- brandService.delete(ids);
- return new Result(true, "删除品牌成功");
- } catch (Exception e) {
- e.printStackTrace();
- return new Result(false, "删除品牌失败");
- }
- }
6.3 前端代码
6.3.1 JS 代码
主要思路: 我们需要定义一个用于存储选中 ID 的数组, 当我们点击复选框后判断是选择还是取消选择, 如果是选择就加到数组中, 如果是取消选择就从数组中移除. 再点击删除按钮时需要用到这个存储了 ID 的数组.
这里我们补充一下 JS 的关于数组操作的知识
(1)数组的 push 方法: 向数组中添加元素
(2)数组的 splice 方法: 从数组的指定位置移除指定个数的元素 , 参数 1 为移除元素的开始位置, 参数 2 为移除的个数
(3)复选框的 checked 属性: 用于判断是否被选中
- // 获取用户点击品牌 ID 的方法
- $scope.selectIds=[]; // 用户勾选的 ID 集合
- $scope.updateSelection=function($event,id){
- if($event.target.checked){ // 被勾选的元素
- $scope.selectIds.push(id); // 才向数组中添加
- }else{
- var index = $scope.selectIds.indexOf(id); // 查找数组中元素的指定位置, 索引从 0 开始
- $scope.selectIds.splice(index,1); // 参数 1 为移除元素的开始位置, 参数 2 为移除的个数
- }
- }
- // 删除品牌的方法
- $scope.dele=function(){
- $http.get('../brand/delete.do?ids='+$scope.selectIds).success(
- function(response){
- if(response.success){
- $scope.reloadList(); // 刷新列表方法
- }else{
- alert(response.message);
- }
- }
- );
- }
- 6.3.2 HTML
(1)修改列表的复选框
<td><input type="checkbox" ng-click="updateSelection($event,entity.id)"></td>
(2)修改删除按钮
<button type="button" class="btn btn-default" title="删除" ng-click="dele()"> <i class="fa fa-trash-o"></i> 删除 </button>
7. 品牌分页条件查询的实现
7.1 需求分析
实现品牌条件查询功能, 输入品牌名称, 首字母后查询, 并分页.
7.2 后端代码
7.2.1 服务接口层
在 pinyougou-sellergoods-interface 工程的 BrandService.java 方法增加方法定义
/** * 分页条件查询全部品牌列表 * @param brand 品牌实体类(查询条件) * @param pageNum 当前页的页码 * @param pageSize 每页要显示的记录数 * @return PageResult */ PageResult findPage(TbBrand brand, Integer pageNum, Integer pageSize);
7.2.2 服务实现层
在 pinyougou-sellergoods-service 工程 BrandServiceImpl.java 实现该方法
@Override public PageResult findPage(TbBrand brand, Integer pageNum, Integer pageSize) { // 设置分页信息, 使用 PageHelper 分页插件 PageHelper.startPage(pageNum, pageSize); // 执行查询, 需要设置查询条件, 即条件查询 TbBrandExample example = new TbBrandExample(); Criteria criteria = example.createCriteria(); if (brand != null) { if (brand.getName() != null && brand.getName().length() > 0) { criteria.andNameLike("%" + brand.getName() + "%"); } if (brand.getFirstChar() != null && brand.getFirstChar().length() > 0) { criteria.andFirstCharLike("%" + brand.getFirstChar() + "%"); } } List<TbBrand> list = brandMapper.selectByExample(example); // 取出分页信息, 分页后, 实际返回的结果 list 类型是 Page<E>, 如果想取出分页信息 // 方式一: 需要强制转换为 Page<E > 后, 使用 Page 对象进行处理 // Page<TbBrand> page = (Page<TbBrand>) list; // return new PageResult(page.getTotal(), page.getResult()); // 方式二: 我们使用 PageInfo 对象对查询出来的结果进行包装, 由于 PageInfo 中包含了非常全面的分页属性, 推荐使用方式二 PageInfo<TbBrand> pageInfo = new PageInfo<>(list); // 创建分页查询时返回的结果类对象 PageResult result = new PageResult(); // 给返回的查询结果对象设置值(即封装数据) result.setTotal(pageInfo.getTotal()); result.setRows(list); return result; }
7.2.3 控制层
在 pinyougou-manager-Web 的 BrandController.java 增加方法
@RequestMapping("/search") public PageResult search(@RequestBody TbBrand brand, Integer page, Integer rows) { PageResult result = brandService.findPage(brand, page, rows); return result; }
7.3 前端代码
JS 中添加品牌条件查询的方法
$scope.searchEntity={}; // 初始化搜索对象 // 品牌条件查询的方法 $scope.search=function(page,rows){ $http.post('../brand/search.do?page='+page+'&rows='+rows,$scope.searchEntity).success( function(response){ // 注意: 请求参数中的 rows 与响应数据的 rows 的区别 $scope.list=response.rows; // 显示当前页数据 $scope.paginationConf.totalItems=response.total; // 更新总记录数 } ); }
修改 reloadList() 方法
// 刷新列表方法 $scope.reloadList=function(){ $scope.search($scope.paginationConf.currentPage, $scope.paginationConf.itemsPerPage); }
将查询按钮绑定的方法 search()修改为 reloadList()方法
<div class="has-feedback"> 品牌名称:<input ng-model="searchEntity.name"> 品牌首字母:<input ng-model="searchEntity.firstChar"> <button class="btn btn-default" ng-click="reloadList()">查询</button> </div>
8. 附录
完整的前端 JS 代码 brand.HTML
文件位置:/pinyougou-manager-Web/src/main/webapp/admin/brand.HTML
<!DOCTYPE HTML> <HTML> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title> 品牌管理 </title> <meta content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no" name="viewport"> <link rel="stylesheet" href="../plugins/bootstrap/css/bootstrap.min.css"> <link rel="stylesheet" href="../plugins/adminLTE/css/AdminLTE.css"> <link rel="stylesheet" href="../plugins/adminLTE/css/skins/_all-skins.min.css"> <link rel="stylesheet" href="../css/style.css"> <script src="../plugins/jQuery/jquery-2.2.3.min.js"> </script> <script src="../plugins/bootstrap/js/bootstrap.min.js"> </script> <!-- 引入 angularjs 文件 --> <script type="text/javascript" src="../plugins/angularjs/angular.min.js"> </script> <!-- 分页组件开始 --> <link rel="stylesheet" href="../plugins/angularjs/pagination.css"> <script src="../plugins/angularjs/pagination.js"> </script> <!-- 分页组件结束 --> <script type="text/javascript"> var App = angular.module('pinyougou', []); // 定义品优购模块 App.controller('brandController', function($scope, $http) { // 定义控制器 // 读取品牌列表数据绑定到表单中 $scope.finAll = function() { $http.get('../brand/findAll.do').success(function(response) { $scope.list = response; }); } }); // 分页控件初始化配置 $scope.paginationConf = { currentPage: 1, // currentPage: 当前页 (初始化) totalItems: 10, // totalItems: 总记录数(初始化) itemsPerPage: 10, // itemsPerPage: 每页记录数(初始化) perPageOptions: [10, 20, 30, 40, 50], // perPageOptions: 分页选项(初始化) onChange: function() { // onChange: 当页码变更后自动触发的方法 $scope.reloadList(); } }; // 刷新列表方法 $scope.reloadList = function() { $scope.search($scope.paginationConf.currentPage, $scope.paginationConf.itemsPerPage); } // 分页方法, 作用是请求后端数据 $scope.findPage = function(page, rows) { // 方法名 findPage 可以自定义 $http.get('../brand/findPage.do?page=' + page + '&rows=' + rows).success(function(response) { // 注意: 请求参数中的 rows 与响应数据的 rows 的区别 $scope.list = response.rows; // 显示当前页数据 $scope.paginationConf.totalItems = response.total; // 更新总记录数 }); } // 新增 / 修改品牌方法 $scope.save = function() { // 方式一: 可以在前端判断是新增方法还是修改方法, 方式二: 可以在后端判断是新增方法还是修改方法 var methodName = 'add'; if ($scope.entity.id != null) { // 如果有 ID methodName = 'update'; // 则执行修改方法 } $http.post('../brand/' + methodName + '.do', $scope.entity).success(function(response) { if (response.success) { $scope.reloadList(); // 刷新列表方法 } else { alert(response.message); } }); } // 根据品牌 ID 查找某一个品牌实体方法, 用于回显数据 $scope.findOne = function(id) { $http.get('../brand/findOne.do?id=' + id).success(function(response) { $scope.entity = response; }); } // 获取用户点击品牌 ID 的方法 $scope.selectIds = []; // 用户勾选的 ID 集合 $scope.updateSelection = function($event, id) { if ($event.target.checked) { // 被勾选的元素 $scope.selectIds.push(id); // 才向数组中添加 } else { var index = $scope.selectIds.indexOf(id); // 查找数组中元素的指定位置, 索引从 0 开始 $scope.selectIds.splice(index, 1); // 参数 1 为移除元素的开始位置, 参数 2 为移除的个数 } } // 删除品牌的方法 $scope.dele = function() { $http.get('../brand/delete.do?ids=' + $scope.selectIds).success(function(response) { if (response.success) { $scope.reloadList(); // 刷新列表方法 } else { alert(response.message); } }); } $scope.searchEntity = {}; // 初始化搜索对象 // 品牌条件查询的方法 $scope.search = function(page, rows) { $http.post('../brand/search.do?page=' + page + '&rows=' + rows, $scope.searchEntity).success(function(response) { // 注意: 请求参数中的 rows 与响应数据的 rows 的区别 $scope.list = response.rows; // 显示当前页数据 $scope.paginationConf.totalItems = response.total; // 更新总记录数 }); } </script> </head> <body class="hold-transition skin-red sidebar-mini" ng-App="pinyougou" ng-controller="brandController"> <!-- .box-body --> <div class="box-header with-border"> <h3 class="box-title"> 品牌管理 </h3> </div> <div class="box-body"> <!-- 数据表格 --> <div class="table-box"> <!-- 工具栏 --> <div class="pull-left"> <div class="form-group form-inline"> <div class="btn-group"> <button type="button" class="btn btn-default" title="新建" data-toggle="modal" data-target="#editModal" ng-click="entity={}"> <i class="fa fa-file-o"> </i> 新建 </button> <button type="button" class="btn btn-default" title="删除" ng-click="dele()"> <i class="fa fa-trash-o"> </i> 删除 </button> <button type="button" class="btn btn-default" title="刷新" onclick="window.location.reload();"> <i class="fa fa-refresh"> </i> 刷新 </button> </div> </div> </div> <div class="box-tools pull-right"> <div class="has-feedback"> 品牌名称: <input ng-model="searchEntity.name"> 品牌首字母: <input ng-model="searchEntity.firstChar"> <button class="btn btn-default" ng-click="reloadList()"> 查询 </button> </div> </div> <!-- 工具栏 /--> <!-- 数据列表 --> <table id="dataList" class="table table-bordered table-striped table-hover dataTable"> <thead> <tr> <th class="" style="padding-right: 0px"> <input id="selall" type="checkbox" class="icheckbox_square-blue"> </th> <th class="sorting_asc"> 品牌 ID </th> <th class="sorting"> 品牌名称 </th> <th class="sorting"> 品牌首字母 </th> <th class="text-center"> 操作 </th> </tr> </thead> <tbody> <tr ng-repeat="entity in list"> <td> <input type="checkbox" ng-click="updateSelection($event,entity.id)"> </td> <td> {{entity.id}} </td> <td> {{entity.name}} </td> <td> {{entity.firstChar}} </td> <td class="text-center"> <button type="button" class="btn bg-olive btn-xs" data-toggle="modal" data-target="#editModal" ng-click="findOne(entity.id)"> 修改 </button> </td> </tr> </tbody> </table> <!-- 数据列表 /--> <!-- {{selectIds}} --> <!-- 分页控件 --> <tm-pagination conf="paginationConf"> </tm-pagination> </div> <!-- 数据表格 /--> </div> <!-- /.box-body --> <!-- 编辑窗口 --> <div class="modal fade" id="editModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-hidden="true"> * </button> <h3 id="myModalLabel"> 品牌编辑 </h3> </div> <div class="modal-body"> <table class="table table-bordered table-striped" width="800px"> <tr> <td> 品牌名称 </td> <td> <input class="form-control" placeholder="品牌名称" ng-model="entity.name"> </td> </tr> <tr> <td> 首字母 </td> <td> <input class="form-control" placeholder="首字母" ng-model="entity.firstChar"> </td> </tr> </table> </div> <div class="modal-footer"> <button class="btn btn-success" data-dismiss="modal" aria-hidden="true" ng-click="save()"> 保存 </button> <button class="btn btn-default" data-dismiss="modal" aria-hidden="true"> 关闭 </button> </div> </div> </div> </div> </body> </HTML>
来源: https://www.cnblogs.com/chenmingjun/p/10273266.html