练手项目1笔记 day03

目标

  • 理解和运用angularJS的service
  • 理解和运用控制器继承
  • 掌握代码生成器的使用
  • 实现规格管理
  • 实现模板管理

1. 前端分层开发

1. 前端服务层的抽取

服务层就是和后端进行交互的部分,是一个函数或对象。如内置服务$http,在不同的控制器中调用同一个服务,提高代码复用性,便于维护。

修改品牌管理代码

var app = angular.module('pinyougou',['pagination']);//定义品优购模块

		// 品牌服务
		app.service("brandService",function ($http) {
			this.findAll = function () {
				return $http.get('../brand/findAll.do');
			};

			this.findPage = function (page,size) {
				return $http.get('../brand/findPage.do?page='+page+'&size='+size);
			};

			this.findOne = function (id) {
				return $http.get('../brand/findOne.do?id='+id);
			};

			this.add = function (entity) {
				return $http.post('../brand/add.do',entity);
			};

			this.update = function (entity) {
				return $http.post('../brand/update.do',entity);
			};

			this.deleteSelection = function (ids) {
				return $http.get('../brand/delete.do?ids='+ids);
			};

			this.search = function (page,size,searchEntity) {
				return $http.post('../brand/search.do?page='+page+'&size='+size,searchEntity)
			}

		});

controller

记得参数加上brandService,save方法修改

app.controller('brandController',function ($scope, $http,brandService) {
			// 查询品牌列表
			$scope.findAll = function () {
				brandService.findAll().success(
						function (response) {
							$scope.list = response;
						}
				);
			};
			
			// 分页控件配置 currentPage当前页 totalItems 总记录数 itemsPerPage 每页记录数
			// perPageOptions分页选项  onChange 当页码变更后自动触发的方法
			$scope.paginationConf = {
				currentPage:1,
				totalItems:10,
				itemsPerPage:10,
				perPageOptions:[10,20,30,40,50],
				onChange:function () {
					$scope.reloadList();
				}
			};

			// 刷新列表
			$scope.reloadList = function(){
				$scope.search($scope.paginationConf.currentPage, $scope.paginationConf.itemsPerPage);
			};

			// 分页
			$scope.findPage = function (page, size) {
				brandService.findPage(page, size).success(
						function (response) {
							$scope.list = response.rows;//显示当前页数据
							$scope.paginationConf.totalItems = response.total;//更新总记录数
						}
				)
			};

			// 根据id查询品牌
            $scope.findOne = function (id) {
                brandService.findOne(id).success(
                    function (response) {
                        $scope.entity = 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.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.deleteSelection = function () {
				brandService.deleteSelection($scope.selectIds).success(
						function (response) {
							if(response.success){
								$scope.reloadList();//刷新
							}else{
								alert(response.message);
							}
						}
				);
			};

			$scope.searchEntity={};
			// 条件查询
			$scope.search = function (page,size) {
				// 混合提交
				brandService.search(page,size,$scope.searchEntity).success(
						function (response) {
							$scope.list = response.rows;//显示当前页数据
							$scope.paginationConf.totalItems = response.total;//更新总记录数
						}
				);
			};
		});

2. 代码分离

将script下的代码分离,主要是service和controller

最终效果

<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>

3. 控制器继承

baseController

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.reloadList();
        }
    };

    // 刷新列表
    $scope.reloadList = function(){
        $scope.search($scope.paginationConf.currentPage, $scope.paginationConf.itemsPerPage);
    };

    // 分页
    $scope.findPage = function (page, size) {
        brandService.findPage(page, size).success(
            function (response) {
                $scope.list = response.rows;//显示当前页数据
                $scope.paginationConf.totalItems = response.total;//更新总记录数
            }
        )
    };

    $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:移除的个数
        }
    };

});

brandController

app.controller('brandController',function ($scope, $controller,$http,brandService) {

    $controller('baseController',{$scope:$scope});

  //...

brand.html

<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>
	<script type="text/javascript" src="../js/controller/baseController.js"></script>

继承为伪继承,scope传递

4. 代码生成

使用代码生成器,生成后,拷贝商家相关。

SellerService修改主键的类型为String。

2. 规格管理

1. 需求和表结构的分析

两个表 tb_specification和tb_specification_option

2. 规格列表

1. 引入JS

修改specification.html

<script src="../plugins/angularjs/angular.min.js"></script>
	<!--分页组件开始-->
	<script 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/specificationService.js"></script>
	<script type="text/javascript" src="../js/controller/specificationController.js"></script>
	<script type="text/javascript" src="../js/controller/baseController.js"></script>

放置分页组件

<tm-pagination conf="paginationConf"></tm-pagination>

指令和表达式

在body元素指定模块名和控制器名

<body class="hold-transition skin-red sidebar-mini" ng-app="pinyougou" ng-controller="specificationController" >

循环表格行

<tbody>
  <tr ng-repeat="entity in list">
    <td><input  type="checkbox" ></td>
    <td>{{entity.id}}</td>
    <td>{{entity.specName}}</td>
    <td class="text-center">                                           
      <button type="button" class="btn bg-olive btn-xs" data-toggle="modal" data-target="#editModal">修改</button>                                           
    </td>
  </tr>
</tbody>

2. 新增规格

1. 新增行的实现

修改specificationController.js

// 增加规格选项行
	$scope.addTableRow = function () {
		$scope.entity.specificationOptionList.push({});
	};

specification.html "新建选项"按钮

 <button type="button" class="btn btn-default" title="新建" data-toggle="modal" data-target="#editModal" ng-click="entity={'specificationOptionList':[]}"><i class="fa fa-file-o"></i> 新建</button>

循环列表行,绑定表格内的编辑框

<tbody>
  <tr ng-repeat="pojo in entity.specificationOptionList">

    <td>
      <input  class="form-control" placeholder="规格选项" ng-model="pojo.optionName">
    </td>
    <td>
      <input  class="form-control" placeholder="排序" ng-model="pojo.orders">
    </td>
    <td>
      <button type="button" class="btn btn-default" title="删除" ng-click="deleTableRow($index)"><i class="fa fa-trash-o"></i> 删除</button>
    </td>
  </tr>
</tbody>

注意:新建时,弹出窗口时对entity初始化,否则添加数据会报错

3. 删除行的实现

还是批量删除

specificationController.js

// 删除规格选项行
	$scope.deleTableRow = function (index) {
		$scope.entity.specificationOptionList.splice(index,1);
	}

删除按钮见上上段代码,记得参数为$index该指令可以获取循环中的索引。

4. 保存

思路:将规格和规格选项参数数据合并为一个对象来传递。

1. pojo中新建个pojogroup包,里面Specification
public class Specification implements Serializable {

    private TbSpecification specification;

    private List<TbSpecificationOption> specificationOptionList;
  // ...
2. dao的修改

要新增规格选项,需要知道新增规格的id,修改TbSpecificationMapper.xml,在insert节点后添加配置

<insert id="insert" parameterType="com.pinyougou.pojo.TbSpecification" >
    <selectKey resultType="java.lang.Long" order="AFTER" keyProperty="id">
      SELECT LAST_INSERT_ID() AS id
    </selectKey>
    insert into tb_specification (id, spec_name)
  ...
3. 修改interface
public interface SpecificationService {
  // ...
  public void add(Specification specification);
}
4. 修改service
@Service
public class SpecificationServiceImpl implements SpecificationService {
  	@Autowired
	private TbSpecificationMapper specificationMapper;

	@Autowired
	private TbSpecificationOptionMapper specificationOptionMapper;
  // ...
  	@Override
	public void add(Specification specification) {
		TbSpecification tbSpecification = specification.getSpecification();
		specificationMapper.insert(tbSpecification);

		List<TbSpecificationOption> specificationOptionList = specification.getSpecificationOptionList();
		for (TbSpecificationOption option : specificationOptionList) {
			option.setSpecId(tbSpecification.getId());//设置规格ID
			specificationOptionMapper.insert(option);//新增规格
		}
	}
}
5. 修改controller
	@RequestMapping("/add")
	public Result add(@RequestBody Specification specification){
		try {
			specificationService.add(specification);
          //...
6. 修改页面specification.html

绑定规格名称

<tr>
  <td>规格名称</td>
  <td><input  class="form-control" placeholder="规格名称" ng-model="entity.specification.specName">  </td>
</tr>

绑定保存按钮

<button class="btn btn-success" data-dismiss="modal" aria-hidden="true" ng-click="save()">保存</button>
7. 删除规格

较为简单,记得删除规格的同时也要删除关联的规格选项

修改service

@Override
	public void delete(Long[] ids) {
		for(Long id:ids){

			// 删除规格
			specificationMapper.deleteByPrimaryKey(id);
			// 删除规格选项
			TbSpecificationOptionExample example = new TbSpecificationOptionExample();
			TbSpecificationOptionExample.Criteria criteria = example.createCriteria();
			criteria.andSpecIdEqualTo(id);
			specificationOptionMapper.deleteByExample(example);
		}		
	}

前端注意两点

删除按钮

<button type="button" class="btn btn-default" title="删除" ng-click="dele()"><i class="fa fa-trash-o"></i> 删除</button>

复选框

<tr ng-repeat="entity in list" ng-click="updateSelection($event,entity.id)">
  <td><input  type="checkbox" ></td>
  <td>{{entity.id}}</td>
  <td>{{entity.specName}}</td>

3. 模板管理

1. 需求和表结构分析

模板主要有两个:1是用于关联品牌和规格;2是定义扩展属性

2. 模板列表

修改type_template.html,引入js

<script src="../plugins/angularjs/angular.min.js"></script>

	<!--分页组件开始-->
	<script 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/typeTemplateController.js"></script>
	<script type="text/javascript" src="../js/controller/baseController.js"></script>

放置分页组件

<!--分页-->
<tm-pagination conf="paginationConf"></tm-pagination>

指令和表达式

<body class="hold-transition skin-red sidebar-mini" ng-app="pinyougou" ng-controller="typeTemplateController">
  ...
  <tbody>
    <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>

3. 品牌下拉列表

使用select2组件完成

要求品牌可以多选

1. 静态品牌下拉列表
  1. 修改type_template.html 引入js
    <link rel="stylesheet" href="../plugins/select2/select2.css" />
    <link rel="stylesheet" href="../plugins/select2/select2-bootstrap.css" />
    <script src="../plugins/select2/select2.min.js" type="text/javascript"></script>
	<script src="../plugins/angularjs/angular.min.js"></script>

	<!--分页组件开始-->
	<script 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/angular-select2.js"></script>
	<script type="text/javascript" src="../js/service/typeTemplateService.js"></script>
	<script type="text/javascript" src="../js/service/brandService.js"></script>
	<script type="text/javascript" src="../js/service/specificationService.js"></script>
	<script type="text/javascript" src="../js/controller/baseController.js"></script>
	<script type="text/javascript" src="../js/controller/typeTemplateController.js"></script>

注意angular-select2的位置在base_pagination之后

  1. 修改typeTemplateController.js,定义品牌列表数据
 $scope.brandList = {data:[{id:1,text:'华为'},{id:2,text:'小米'},{id:3,text:'苹果'}]};
  1. 在type_template.html中,用select2组件实现多选下拉框
<td>关联品牌</td>
<td>
  <input select2 select2-model="entity.brandIds" config="brandList" multiple placeholder="选择品牌(可多选)"
         class="form-control" type="text" />

其中 multiple表示可多选;config配置数据来源,select2-model用于指定用户选择后提交的变量。

2. 后端数据支撑

让数据从数据库中提取。

1. pinyougou.dao

在TbBrandMapper.xml中添加SQL语句配置

<select id="selectOptionList" resultType="java.util.Map">
    select id,name as text from tb_brand
  </select>

在TbBrandMapper中添加方法定义

List<Map> selectOptionList();
2. pinyougou-sellergoods-interface

BrandService增加方法定义

// 复选下拉框的实现
    List<Map> selectOptionList();
3. service
 @Override
    public List<Map> selectOptionList() {
        return brandMapper.selectOptionList();
    }
4. cotroller
 @RequestMapping("/selectOptionList")
    public  List<Map> selectOptionList(){
        return brandService.selectOptionList();
    }
5. 测试

通过

3. 前端修改
1. 修改brandService.js

增加方法

this.selectOptionList = function () {
        return $http.post('../brand/selectOptionList.do');
    }
2. 修改typeTemplateController.js

使用服务层的方法,添加依赖注入

 //控制层 
app.controller('typeTemplateController' ,function($scope,$controller   ,typeTemplateService, brandService,specificationService){...}

使用服务方法实现查询,结果赋值给变量

	// 多选下拉框
	// $scope.brandList = {data:[{id:1,text:'华为'},{id:2,text:'小米'},{id:3,text:'苹果'}]};
	$scope.brandList = {data:[]};
	// 读取品牌列表
	$scope.findBrandList = function () {
		brandService.selectOptionList().success(
			function (response) {
				$scope.brandList = {data:response};
			}
		);
	}
3. 修改type_template.html

引入brandService.js

body里面 添加初始化指令

<body class="hold-transition skin-red sidebar-mini" ng-app="pinyougou" ng-controller="typeTemplateController" ng-init="findBrandList();findSpecList()">

4. 新增模板

修改type_template.html,绑定文本框

<td>商品类型</td>
<td><input  class="form-control" placeholder="商品类型" ng-model="entity.name">  </td>

保存按钮

<button class="btn btn-success" data-dismiss="modal" aria-hidden="true" ng-click="save()">保存</button>

5. 修改模板

修改typeTemplateController.js的findOne方法

从数据库中查询的到的是字符串,必须转化为json对象才能实现信息的回显

	//查询实体 
	$scope.findOne=function(id){				
		typeTemplateService.findOne(id).success(
			function(response){
				$scope.entity= response;
				// 转换字符串为json
				$scope.entity.brandIds = JSON.parse($scope.entity.brandIds);
				$scope.entity.specIds = JSON.parse($scope.entity.specIds);
				$scope.entity.customAttributeItems = JSON.parse($scope.entity.customAttributeItems);
			}
		);				
	}

6. 删除模板

修改type_template.html

表格中的复选框

<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.brandIds}}</td>

删除按钮

<button type="button" class="btn btn-default" title="删除" ng-click="dele()"><i class="fa fa-trash-o"></i> 删除</button>

7. 优化模板列表的显示

现在显示的是json格式,不利于用户的查询

需要显示text内容

将方法写到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;
    }

页面使用该函数转换

<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.brandIds}}</td>
  <td>{{jsonToString(entity.specIds,'text')}}</td>
  <td>{{jsonToString(entity.customAttributeItems,'text')}}</td>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值