目标1:理解和运用angularJS的service 目标2:理解和运用控制器继承 目标3:掌握代码生成器的使用 目标4:实现规格管理 目标5:实现模板管理
一、自定义服务:就是将之前的所有与后台请求相关代码抽取出
1.在brand.html中拆分service和controller
app.service('brandService',function($http){ this.findAll = function(){ return $http.get('../brand/findAll.do'); } this.add = function(entity){ return $http.post('../brand/add.do',entity) } this.update = function(entity){ return $http.post('../brand/update.do',entity) } this.findOne = function(id){ return $http.get('../brand/findOne.do?id='+id); } this.dele = function(ids){ return $http.get('../brand/delete.do?ids='+ids); } this.findPage = function(pageNum,pageSize,searchEntity){ return $http.post('../brand/findPage.do?pageNum='+pageNum+"&pageSize="+pageSize,searchEntity); } })
app.controller('brandController',function($scope,brandService){ $scope.save = function(){ //其他方法都参照修改进行重新调用 var object = null; if($scope.entity.id != null){ object = brandService.update($scope.entity); }else{ object = brandService.add($scope.entity); } object.success( function(response){ if(response.success){ $scope.reloadList(); }else{ alert(response.message); } } ) } ....... }
二、代码分离:分离出base,base_pagination,brandService.js,brandController.js
1.pinyougou-manager-web的js目录中增加base_pagination.js和base.js文件
//base_pagination.js内容 var app = angular.module('pinyougou',['pagination']); //base.js内容 var app = angular.module('pinyougou',[]);
2.pinyougou-manager-web的js目录中增加service文件夹,新增文件brandService.js并拷贝之前service代码
3.pinyougou-manager-web的js目录中增加controller文件夹,新增文件brandController.js并拷贝控制代码
4.在brand.html中进行导入注意导入顺序,注意script必须写全
<script type="text/javascript" src="../js/base_pagination.js" ></script> <script type="text/javascript" src="../js/service/brandService.js" ></script> <script type="text/javascript" src="../js/controller/brandController.js" ></script>
三、控制器继承
1.在controller目录中创建baseController.js文件,抽取出如下方法从brandController.js
app.controller('baseController',function($scope){ //分页控件配置currentPage:当前页 totalItems :总记录数 itemsPerPage:每页记录数 perPageOptions :分页选项 onChange:当页码变更后自动触发的方法 $scope.paginationConf = { currentPage: 1, totalItems: 10, itemsPerPage: 10, perPageOptions: [10, 20, 30, 40, 50], onChange: function(){ $scope.findPage(); } }; $scope.selectIds=[];//用户勾选的ID集合 //用户勾选复选框 $scope.updateSelection=function($event,id){ if($event.target.checked){ $scope.selectIds.push(id);//push向集合添加元素 }else{ var index= $scope.selectIds.indexOf(id);//查找值的 位置 $scope.selectIds.splice(index,1);//参数1:移除的位置 参数2:移除的个数 } } $scope.hasCheck = function(id){ if($scope.selectIds.indexOf(id) != -1){ return true; }else{ return false; } } })
brandController.js优化后的代码为
app.controller('brandController', function($scope,$controller, brandService) { //继承,并在方法中参数增加$controller $controller('baseController',{$scope:$scope}) $scope.findAll = function() { brandService.findAll.success(function(response) { $scope.list = response; }); } $scope.save = function() { var object = null; if ($scope.entity.id != null) { object = brandService.update($scope.entity); } else { object = brandService.add($scope.entity); } object.success(function(response) { if (response.success) { $scope.reloadList(); } else { alert(response.message); } }) } $scope.findOne = function(id) { brandService.findOne(id).success(function(response) { $scope.entity = response; }) } $scope.dele = function() { if (confirm('确定要删除吗')) { brandService.dele($scope.selectIds).success(function(response) { if (response.success) { $scope.reloadList(); } alert(response.message); }) } } $scope.searchEntity = {}; $scope.findPage = function(){ brandService.findPage( $scope.paginationConf.currentPage, $scope.paginationConf.itemsPerPage, $scope.searchEntity).success( function(response){ $scope.list = response.rows; $scope.paginationConf.totalItems = response.total; } ) } })
2.在brand.html中在引入brandController.js文件前导入
<script type="text/javascript" src="../js/controller/baseController.js" ></script>
四、代码生成器生成规格及模版相关文件(之前的品牌也替换掉)
1.没有中文和空格的目录下运行heima_code_util.exe,
生成的包名为com.pinyougou.sellergoods,拷贝文件列表
//sellergoods-interface模块需要拷贝接口文件 BrandService.java,SpecificationService.java,TypeTemplateService.java //sellergoods-service模块需要拷贝实现类 BrandServiceImpl.java,SpecificationServiceImpl.java,TypeTemplateServiceImpl.java //manager-web模块拷贝 BrandController.java,SpecificationController.java,TypeTemplateController.java(修改下包名) //manager-web模块的前端js/controller目录下要拷贝的三个文件 baseController.js,brandController.js, specificationController.js,typeTemplateController.js //manager-web模块的前端js/service目录下要替换的两个文件 brandService.js,specificationService.js,typeTemplateService. //manager-web模块的前端js目录 base.js,base_pagination.js
五、规格列表
1.在specification.html页面中引入js文件
<script src="../plugins/angularjs/angular.min.js"></script> <script src="../plugins/angularjs/pagination.js"></script> <script src="../js/base_pagination.js" ></script> <script src="../js/service/specificationService.js" ></script> <script src="../js/controller/baseController.js"></script> <script src="../js/controller/specificationController.js" ></script>
2.body中增加ng-app="pinyougou" ng-controller="specificationController"
3.td中增加{{entity.属性名取值}},tr中增加ng-repeat="entity in list"
4.增加分页控件 <tm-pagination conf="paginationConf"></tm-pagination>
六、为规格页面的新增弹出框新增行
实现思路:就是通过对entity中定义得sepcOptionList数组增加空对象来完成列表得新增(依赖数据绑定)
1.页面顶部的新建按钮添加点击事件ng-click="entity = {specOptionList:[],specification:{}}" //进行初始化
2.specificationController.js中增加
//点击增加行的效果 $scope.addTableRow = function(){ $scope.entity.specOptionList.push({}); //注意这里是大括弧,大括弧是对象,代表加新对象 }
3.规格新增按钮增加 ng-click="addTableRow()点击事件
//specification.html //113行 <tr ng-repeat="pojo in entity.specOptionList"> //115行 <input ng-model="pojo.optionName" class="form-control" placeholder="规格选项"> //118行 <input ng-model="pojo.orders" class="form-control" placeholder="排序">
七、删除规格选项行
1.在删除按钮上调用ng-click="deleTableRow($index)"方法
2.在specificationController.js中增加
$scope.deleTableRow = function(index){ $scope.entity.specOptionList.splice(index,1); }
八、规格新增
1.在pojo子模块建立com.pinyougou.pojogroup包新增文件Specification
package com.pinyougou.pojogroup; public class Specification implements Serializable{ private TbSpecification specification; private List<TbSpecificationOption> specOptionList; public TbSpecification getSpecification() { return specification; } public void setSpecification(TbSpecification specification) { this.specification = specification; } public List<TbSpecificationOption> getSpecOptionList() { return specOptionList; } public void setSpecOptionList(List<TbSpecificationOption> specOptionList) { this.specOptionList = specOptionList; } }
2.在TbSpecificationMapper.xml中的insert部分增加如下代码,目的是插入后将last_insert_id赋值给id属性
<selectKey resultType="java.lang.Long" order="AFTER" keyProperty="id"> select last_insert_id() as id </selectKey>
3.SpecificationService接口层修改为
public void add(Specification specification);
4.SpecificationServiceImpl服务层修改为
@Override public void add(Specification specification) { specificationMapper.insert(specification.getSpecification()); // 设置规格ID for (TbSpecificationOption so : specification.getSpecOptionList()) { so.setSpecId(specification.getSpecification().getId()); specificationOptionMapper.insert(so); } }
5.SpecificationController修改为
public Result add(@RequestBody Specification specification) //参数去掉tb
6.specification.html,规格名称的输入框中增加ng-model="entity.specification.specName",保存按钮增加ng-click="save()"方法的调用
7.在specificationController.js文件中对save方法中的判断增加
//if($scope.entity.id != null) 改为 if($scope.entity.specification.id != null) //因为entity对象已经是自己封装的Specification
九、规格修改
1.返回类型改成组合实体类,之前是TbSpecification
public Specification findOne(Long id);
2.修改SpecificationServiceImpl.java
public Specification findOne(Long id){ //初始化 Specification specification = new Specification(); //设置规格对象 specification.setSpecification(specificationMapper.selectByPrimaryKey(id)); //查询所有规格选项列表 TbSpecificationOptionExample example = new TbSpecificationOptionExample(); com.pinyougou.pojo.TbSpecificationOptionExample.Criteria createCriteria = example.createCriteria(); createCriteria.andSpecIdEqualTo(id); List<TbSpecificationOption> specificationOptionList = specificationOptionMapper.selectByExample(example); //设置规格选项 specification.setSpecificationOptionList(specificationOptionList); return specification; }
3.修改SpecificationController.java去掉TbSpecification改为Specification
4.页面点击修改按钮调用 ng-click="findOne(entity.id)",
重点修改js中if($scope.entity.specification.id!=null)否则新增跟修改无法正常判断
5.sellergoods-interface的update方法类型改成组合实体类TbSpecification改成Specification
6.sellergoods-service的update方法修改为
public void update(Specification specification){ //获取规格实体 TbSpecification tbspecification = specification.getSpecification(); specificationMapper.updateByPrimaryKey(tbspecification); //清除原来规格对应的规格选项 TbSpecificationOptionExample example = new TbSpecificationOptionExample(); com.pinyougou.pojo.TbSpecificationOptionExample.Criteria criteria = example.createCriteria(); criteria.andSpecIdEqualTo(tbspecification.getId()); specificationOptionMapper.deleteByExample(example); //获取规格选项集合 List<TbSpecificationOption> specificationOptionList = specification.getSpecificationOptionList(); for (TbSpecificationOption option : specificationOptionList) { option.setSpecId(tbspecification.getId());//设置规格id specificationOptionMapper.insert(option);//新增规格 } }
7.manager-web的SpecificationController.java修改update(@RequestBody Specification specification)去掉Tb
十、规格删除
1.在SpecificationServiceImpl.java的dele方法中
public void delete(Long[] ids) { for(Long id:ids){ //删除规格表数据 specificationMapper.deleteByPrimaryKey(id); //清除原来规格对应的规格选项 TbSpecificationOptionExample example = new TbSpecificationOptionExample(); com.pinyougou.pojo.TbSpecificationOptionExample.Criteria criteria = example.createCriteria(); criteria.andSpecIdEqualTo(id); specificationOptionMapper.deleteByExample(example); } }
2.在页面中的checkbox中增加ng-click="updateSelection($event,entity.id)",删除按钮增加ng-click="dele()"
十一、模版列表得显示,调整好界面,即后端及前端文件都已拷贝到项目中
1.type_template.html导入步骤一:js相关文件,步骤二:body中增加,步骤三:table下面加分页控件
<script type="text/javascript" src="../plugins/angularjs/angular.min.js"></script> <script type="text/javascript" src="../plugins/angularjs/pagination.js"></script> <link rel="stylesheet" href="../plugins/angularjs/pagination.css"> <script type="text/javascript" src="../js/base_pagination.js" ></script> <script type="text/javascript" src="../js/service/typeTemplateService.js" ></script> <script type="text/javascript" src="../js/controller/baseController.js" ></script> <script type="text/javascript" src="../js/controller/typeTemplateController.js" ></script> ... <body class="hold-transition skin-red sidebar-mini" ng-app="pinyougou" ng-controller="typeTemplateController"> ... <tr ng-repeat="entity in list"> <td><input type="checkbox"></td> <td>{{entity.id}}</td> <td>{{entity.name}}</td> <td>{{entity.brandIds}}</td> <td>{{entity.specIds}}</td> <td>{{entity.customAttributeItems}}</td> <td class="text-center"> <button type="button" class="btn bg-olive btn-xs" data-toggle="modal" data-target="#editModal" >修改</button></td> </tr> ... </table> <!--数据列表/--> <tm-pagination conf="paginationConf"></tm-pagination>
十二、模版新增的品牌下拉列表
1.type_template.html页面引入angular-select2.js文件,编辑框改为select2
<script type="text/javascript" src="../plugins/angularjs/angular.min.js"></script> <script type="text/javascript" src="../plugins/angularjs/pagination.js"></script> <link rel="stylesheet" href="../plugins/angularjs/pagination.css"> <script type="text/javascript" src="../js/base_pagination.js"></script> //跟多选框相关的引用务必放在base_pagination.js下面 <script src="../plugins/select2/select2.min.js" type="text/javascript"></script> <script type="text/javascript" src="../plugins/select2/angular-select2.js"> </script> <script type="text/javascript" src="../js/service/typeTemplateService.js"></script> <script type="text/javascript" src="../js/controller/baseController.js"></script> <script type="text/javascript" src="../js/controller/typeTemplateController.js"></script> //关联品牌的增加编辑框 <td>关联品牌</td> <td> <input select2 select2-model="entity.brandIds" config="brandList" multiple placeholder="选择品牌(可多选)" class="form-control" type="text"/> </td>
2.typeTemplateController.js增加测试数据,为了让页面有下拉选项注意JSON数据格式!!!!!
$scope.brandList = {data:[{id:1,text:'联想'},{id:2,text:'华为'},{id:3,text:'中兴'}]};
3.准备好下拉框后,准备从数据库获取brandList中得内容,在TbBrandMapper.xml文件最后增加
<select id="selectOptionList" resultType="java.util.Map"> select id,name as text from tb_brand </select>
4.TbBrandMapper.java增加查询规格方法
List<Map> selectOptionList();
5.BrandService.java增加
public List<Map> selectOptionList();
6.BrandServiceImpl.java增加方法
public List<Map> selectOptionList() { // TODO Auto-generated method stub return brandMapper.selectOptionList(); }
7.BrandController.java增加方法
@RequestMapping("/selectOptionList") public List<Map> selectOptionList(){ return brandService.selectOptionList(); }
7.brandService.js增加
//下拉列表 this.selectOptionList = function(){ return $http.get('../brand/selectOptionList.do'); }
8.在typeTemplateController.js中加上brandService的引入
//读取品牌列表 $scope.brandList={data:[]}; //可以避免页面的一些初始值错误 $scope.findBrandList = function(){ brandService.selectOptionList().success( function(response){ $scope.brandList = {data:response}; } ); }
9.在type_template.html中引入brandService.js文件
<script type="text/javascript" src="../js/service/brandService.js" ></script> ..//body中增加方法的调用 <body ng-init="findBrandList()>
十三、模版新增的规格下拉列表
1.TbSpecificationMapper.xml增加查询
<select id="selectOptionList" resultType="java.util.Map"> select id,spec_name as text from tb_specification </select>
2.TbSpecificationMapper.java增加List<Map> selectOptionList();
3.SpecificationService.java增加public List<Map> selectOptionList();
4.SpecificationServiceImpl.java
@Override public List<Map> selectOptionList() { // TODO Auto-generated method stub return specificationMapper.selectOptionList(); }
5.SpecificationController.java增加
@RequestMapping("/selectOptionList") public List<Map> selectOptionList(){ return specificationService.selectOptionList(); }
6.specificationService.js增加
//下拉列表 this.selectOptionList = function(){ return $http.get('../specification/selectOptionList.do'); }
7.在typeTemplateController.js中加上specificationService的引入
$scope.specList={data:[]}; //可以避免页面的一些初始值错误 //读取规格列表 $scope.findSpecList = function(){ specificationService.selectOptionList().success( function(response){ $scope.specList = {data:response}; } ); }
8.在type_template.html页面中引入
<script type="text/javascript" src="../js/service/specificationService.js" ></script> ... <body中ng-init="findBrandList();findSpecList()"> ... <td>关联规格</td> <td> <input select2 select2-model="entity.specIds" config="specList" multiple placeholder="选择规格(可多选)" class="form-control" type="text"/> </td>
十四、增加删除扩展属性行
1.在 typeTemplateController.js
$scope.addTableRow = function(){ $scope.entity.customAttributeItems.push({}); } $scope.deleTableRow = function(index){ $scope.entity.customAttributeItems.splice(index,1); }
2.在type_template.html页面,
新建按钮增加ng-click="entity = {customAttributeItems:[]}"对值进行初始化,
新增扩展属性按钮增加ng-click="addTableRow()",
删除按钮增加ng-click="deleTableRow($index)"
//扩展属性删除多余的tr,修改tr为动态 <tr ng-repeat="pojo in entity.customAttributeItems"> <td><input type="checkbox" class="icheckbox_square-blue" ></td> <td><input class="form-control" placeholder="属性名称" ng-model="pojo.text"></td> <td><button type="button" class="btn btn-default" title="删除" ng-click="deleTableRow($index)"><i class="fa fa-trash-o"></i> 删除</button></td> </tr>
十五、新增模版
1.type_template.html在商品类型输入框中增加ng-model="entity.name"
2.type_template.html在保存按钮增加ng-click="save()"
十六、修改模板
1.type_template.html修改按钮增加ng-click="findOne(entity.id)";
2.typeTemplateController.js中的查询实体方法,增加三处需要将字符串转json对象的地方
//查询实体 $scope.findOne=function(id){ typeTemplateService.findOne(id).success( function(response){ $scope.entity= response; $scope.entity.brandIds = JSON.parse($scope.entity.brandIds); $scope.entity.specIds = JSON.parse($scope.entity.specIds); $scope.entity.customAttributeItems = JSON.parse($scope.entity.customAttributeItems); } ); }
十七、删除模版
1.type_template.html的checkbox部分增加<input type="checkbox" ng-click="updateSelection($event,entity.id)">
2.删除按钮增加ng-click="dele()"
十八、优化模版列表显示,将列表数据转成只有text的内容
1.baseController.js增加
$scope.jsonToString=function(jsonString,key){ var json= JSON.parse(jsonString); var value=""; for(var i=0;i<json.length;i++){ if(i>0){ value+=","; } value +=json[i][key]; } return value; }
2.页面中的属性部分加上{{jsonToString(entity.brandIds,'text')}}