品优购_day03

品优购_day03

1. 自定义服务

自定义服务,而服务会封装一些操作。在不同的控制器中可以调用同一个服务,这样服务的代码将会被重用。页面需要用到该服务时,直接引入即可。

<script type="text/javascript" src="../js/base_pagination.js"></script>

同时body标签要指定ng-app="pinyougou"
  • base_pagination.js
var app=angular.module('pinyougou',['pagination']);
//分页,定义模块时引入pagination模块

再用app定义不同的Service服务层,如:

  • brandService.js
app.service('brandService',function($http){  	
	
	this.findAll=function(){
		return $http.get('../brand/findAll.do');		
	}
}

Controller控制层再引入需要的服务即可,如:

  • brandController.js
//控制层 
app.controller('brandController' ,function($scope,brandService){	 
	brandService.findAll=function(){
		brandService.findAll().success(
			function(response){
				$scope.list=response;
			}			
		);
	}  

2. 控制器继承

有些功能是每个页面都有可能用到的,比如分页,复选等等,如果我们再开发另一个功能,还需要重复编写,可通过继承的方式让这些通用的功能只写一次。

  • 建立父控制器baseController.js
app.controller('baseController' ,function($scope){	
   
	$scope.updateSelection = function($event, id) {		
		if($event.target.checked){
			$scope.selectIds.push( id);			
		}else{
			var idx = $scope.selectIds.indexOf(id);
            $scope.selectIds.splice(idx, 1);
		}
}  
  • brandController.js可继承baseController.js
 //控制层 
app.controller('brandController' ,function($scope,$controller,brandService){	
	
	$controller('baseController',{$scope:$scope});
    //$controller也是angular提供的一个服务,可以实现伪继承,实际上就是与baseController共享$scope
	
	$scope.findAll=function(){
		brandService.findAll().success(
			function(response){
				$scope.list=response;
			}			
		);
	}    

由于brandController继承了baseController,所以brandPro.html要引入baseController.js,理论上要在brandController.js前引入,实测引入位置在引入brandController.js之前之后都可以。

3. 代码生成器

可使用《黑马程序员代码生成器2.4》来完成基础代码的编写,生成后将代码拷贝到工程中,步骤如下:

  1. 将HeimaCodeUtil_V2.4_32文件夹拷贝到不含中文和空格的目录下;

  2. 运行heima_code_util.exe,填写对应信息,先点击测试连接,成功后选择数据库即可;

  1. 点击下一步,选择模板为SSM+dubbox+angularJS(服务层+WEB层),选择代码生成路径,点击生成代码,然后拷贝代码到工程即可。

    这个模板不会生成数据访问层和实体类,因为之前已经用逆向工程完成了数据访问层与实体类的生成。

4. 代码编写重难点

4.1 新增规格选项行

  1. specification.html

给新建规格选项按钮添加addTableRow()方法:

<button type="button" class="btn btn-default" title="新建"  ng-click="addTableRow()"><i class="fa fa-file-o"></i> 新增规格选项</button>

修改specification.html 新建按钮,弹出窗口时对entity进行初始化,可以清空上次添加规格遗留的内容;另外如果不对entity初始化向集合添加数据时会出错。

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

entity是一个组合,包含TbSpecification和List

一开始是再js中初始化:

$cope.entity.specificationOptionList=[];//这种写法是错误的,因为entity为null
$scope.entity={specification:{},specificationOptionList:[]};//定义entity初始结构,也可写为$scope.entity={specificationOptionList:[]},specification:{}可省略,因为specification不是一个集合。

由于每次弹出新建规格窗口时要清空输入框中的内容,所以改到了在每次点击新建按钮时初始化。

  1. 绑定编辑框的内容

新增规格,数据分为两部分,一部分是规格名称,可封装到specification这个pojo中,另一部分是规格选项集合specificationOptionList;再将这两部分数据封装到一个对象entity中。

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

<input ng-model="tbSpecificationOption.optionName"  class="form-control" placeholder="规格选项" > 
<input ng-model="tbSpecificationOption.orders" class="form-control" placeholder="排序"> 
  1. specificationController.js
$scope.addTableRow=function(){
		$scope.entity.specificationOptionList.push({});
		//specificationOptionList的格式为[{},{}...]
}

4.2 删除规格选项行

实现思路:在规格选项每一行将索引值传递给specificationOptionList集合,在集合中删除。

  1. 修改删除按钮,传递当前行索引值
	<button type="button" class="btn btn-default" title="删除" ng-click="deleTableRow($index)"><i class="fa fa-trash-o"></i> 删除</button>

  1. specificationController.js
$scope.deleTableRow=function(index){
 	$scope.entity.specificationOptionList.splice(index,1);
}

4.3 保存新增规格数据

实现思路:规格和规格选项数据合并成一个对象entity来传递,则需要用一个组合pojo来接收传递过来的对象。在业务逻辑中,得到组合对象中的规格和规格选项列表,先插入规格数据到tb_specification返回规格id,然后循环插入规格选项数据到tb_specification_option,因为插入规格选项时需要规格id。

  1. 插入规格后,获取规格id

    在TbSpecificationMapper.xml中的insert节点插入selectKey获取刚插入的规格id。

<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)
    values (#{id,jdbcType=BIGINT}, #{specName,jdbcType=VARCHAR})
  </insert>
  1. 建立组合pojo
public class SpecificationAndOption implements Serializable {
	private TbSpecification specification;//规格
	private List<TbSpecificationOption> specificationOptionList;//规格选项
    //......get/set
}
  1. 业务层SpecificationService

    插入规格后,获取到了规格id,插入规格选项前要先设置规格选项的规格id。

public void add(SpecificationAndOption sao) {
		specificationMapper.insert(sao.getSpecification());//插入规格
		for(TbSpecificationOption tso:sao.getSpecificationOptionList()) {
			//注意这里要设置id
			tso.setSpecId(sao.getSpecification().getId());
			specificationOptionMapper.insert(tso);
		}
	}

4.4 品牌下拉列表(select2组件)

  1. 认识select2

页面使用要引入select2的js文件。

  1. 在type_template.html 用select2组件实现多选下拉框
<input select2  select2-model="entity.brandIds" config="brandList" multiple placeholder="选择品牌(可多选)" class="form-control" type="text"/>	

select2 表示它是一个多选框;multiple 表示可多选;config用于配置数据来源;select2-model用于指定用户选择后提交的变量。

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

查询出的数据格式如下: [{"id":1,"text":"联想"},{"id":3,"text":"三星"}],所以用List里面封装Map。

<select id="selectOptionList"  resultType="java.util.Map" >
select id,name as text from tb_brand
//因为id,text这两个key的名称是固定的
</select>

4.5 扩展属性

  • type_template.html

点击“新建”,执行实体的初始化操作:ng-click="entity={'customAttributeItems':[]}",点击“新增扩展属性”时增加一行:ng-click="addTableRow()"

4.6 根据id查询模板

  1. typeTemplateController.js

    查询模板实体

$scope.findOne=function(id){				
		typeTemplateService.findOne(id).success(
			function(response){
				$scope.entity= response;				$scope.entity.brandIds=JSON.parse($scope.entity.brandIds);
//将json字符串转换为json对象
//转换品牌列表	
               $scope.entity.specIds=JSON.parse($scope.entity.specIds);
//转换规格列表	
               $scope.entity.customAttributeItems=JSON.parse($scope.entity.customAttributeItems);//转换品牌列表
			}
		);				
	}

例如:从数据库中查询出来的规格列表是字符串:[{"id":27,"text":"网络"},{"id":32,"text":"机身内存"}],必须将其转换为json对象才能实现信息的回显(但经过我的测试发现不转换为json对象也可以显示)。

  1. baseController.js

    最终页面显示的数据不是json字符串,而是text属性值,以","分割,所以需要从json字符串提取属性值。

//提取json字符串数据中的某个属性,返回拼接字符串,以逗号分隔
	$scope.json2String=function(jsonStr,key){
		var json=JSON.parse(jsonStr);//将json字符串转为json对象
		var str="";
		for(var i=0;i<json.length;i++){
			if(i>0){
				str+=",";
			}
			str+=json[i][key];//获取第i个键名为key的值
			//[{"id":27,"text":"网络"},{"id":32,"text":"机身内存"}]
		}
		return str;
	}
  1. type_template.html
//调用方法转换json字符串
<td>{{json2String(entity.brandIds,'text')}}</td>
<td>{{json2String(entity.specIds,'text')}}</td>				<td>{{json2String(entity.customAttributeItems,'text')}}</td>
原文地址:https://www.cnblogs.com/ALiWang/p/12871947.html