`

Extjs中可编辑表格,树,触发按钮和复选框的结合使用

阅读更多

 

Extjs中可编辑表格,树,触发按钮和复选框的结合使用

 

1.数据源Store:

/*1.创建Record*/
var costRecord = new Ext.data.Record.create([
	{name:"id",type:"int"},
	{name:"xmid",type:"int"},
	{name:"subject",type:"string"},
	{name:"subjectId",type:"string"},
	{name:"planCost",type:"string"},
	{name:"actualCost",type:"string"}
]);

/*2.创建Store*/
var costStore = new Ext.data.Store({  //注意JsonStore和Store的区别
	url:"getProjectCost.eva?doType=getProjectCost",
	reader: new Ext.data.JsonReader({
		root:"data"
	},costRecord)
});

 

2.列ColumnModel:

var selectedCostRow;//定义全局变量,获取点击列表某一行时通过复选框获得的行号。
//复选框
var costSm = new Ext.grid.CheckboxSelectionModel();
/* costSm.handleMouseDown = Ext.emptyFn; */
//触发域
var costTrigger = new Ext.form.TriggerField({
	emptyText:"请选择...",
	allowBlank:false,
	readOnly:true,
	onTriggerClick:function(e){    //单击触发按钮触发的事件
		selectedCostRow = costSm.getSelected();
		costTreeWin.show();
	}
});
var costCm = new Ext.grid.ColumnModel({
	columns:[
		costSm,   //在列中加上定义的复选框
		{
			header:"编号",
			dataIndex:"id",
			width:200,
			hidden:true
		},{
			header:"项目编号",
			dataIndex:"xmid",
			width:200,
			hidden:true,
			editor:new Ext.form.TextField({   //此处加上可编辑文本框
				id:"costXmid"
			})
		},{
			header:"支出内容(经济科目)",
			dataIndex:"subject",
			width:200,
			editor:costTrigger       //此处加上触发域
		},{
			header:"经济科目ID",
			dataIndex:"subjectId",
			width:200,
			hidden:true
		},{
			header:"计划支出数(单位:元)",
			dataIndex:"planCost",
			width:200,
			editor:new Ext.form.TextField({
				allowBlank: false
			})
		},{
			header:"实际支出数(单位:元)",
			dataIndex:"actualCost",
			width:200,
			editor:new Ext.form.TextField({
				allowBlank: false
			})
		}
	]
});

注意:若加上了costSm.handleMouseDown = Ext.emptyFn;  则点击复选框才能选中,点击行不能选中。

若不加这句话,则点击行即可选中复选框!

 

3.可编辑表格面板:EditorGridPanel

/*4.创建表格面板*/
var costGrid = new Ext.grid.EditorGridPanel({
	cm:costCm,
	sm:costSm,          //表格中也必须加上定义的复选框才行
	store:costStore,
	clicksToEdit:1,    //设置点击几次才可以编程
	stripeRows: true,  //斑马线的表格
	loadMask:{msg:'正在加载数据,请稍侯……'},  
	height:480,
	width:630,
	tbar:[
		{
			text:"保存",
			iconCls:"save",
			handler:saveCost    //点击调用保存方法
		},{
			text:"增加",
			iconCls:"add",
			handler:function(){
				var newCost = new costRecord({   //此处创建新的Record
	                	id:-1,
	                	xmid:Ext.getCmp("costXmid").getValue(),
	                	subject:'',
	                	subjectId:'',
	                	planCost:'',
	                	actualCost:''
	                });
	                costGrid.stopEditing();			//关闭表格的编辑状态
	                costStore.add(newCost);
	                //store.insert(0, newCost); 	//创建的Record插入store的第一行
	                //store.insert(store.getCount(), newCost); //创建的Record插入store的最后一行
	                costGrid.startEditing(0, 0);	//激活第一行第一列的编辑状态
			}
		},{
			text:"删除",
			iconCls:"remove",
			handler:removeCost      //点击调用删除方法
		}
	]
});



/*创建保存收支明细方法,只保存修改过的信息*/
function saveCost(){
	//只提交修改过的记录
	var rcds = costStore.getModifiedRecords();     //获取修改过的记录集Records
	if(rcds&&rcds.length>0){
		Ext.Msg.wait("正在保存...");
    	var rows=new Array();
		for(var i=0;i<rcds.length;i++){
    		var rs = rcds[i];    //获取指定下标的某一行的记录Record
			var row=new Object();
    		var fields=rs.data;    //获取该行记录的数据Data
    		row = {id:fields.id,xmid:fields.xmid,subjectId:fields["subjectId"],planCost:fields["planCost"],actualCost:fields["actualCost"]};
    		rows.push(row);    //注意此处获取属性方式:obj.id或者obj["id"]
		}                  //因为此处obj是data,这些id,name都是data的属性
                                   //如果直接用record,则可以用它在Extjs中定义的get方法:rs.get("id")
		Ext.Ajax.request({   
	        url: 'updateProjectCost.eva?doType=updateProjectCost',   
	        method:'POST',
	        timeout:300000,  
	        success: result,
	        failure: function(){Ext.Msg.alert('信息','未成功提交数据!'); },
	        params:{updateSets :Ext.encode(rows)} //将数组转化为JSON字符串!!!
	    });
		function result(response, options){
			var result = Ext.util.JSON.decode(response.responseText);
			if(result.success){
           	  	Ext.Msg.hide();
           	  	Ext.Msg.show({
           	  			title:'成功',
						msg: '数据保存成功',
						buttons: Ext.Msg.OK,
						icon: Ext.MessageBox.INFO
			  	});	
			  	//保存成功后刷新修改过的脏数据。
			  	costStore.rejectChanges();
			  	costStore.reload();
           }else{
           	  Ext.Msg.hide();
           	  Ext.Msg.alert('信息','保存数据未成功!');
           }
	 	} 
	}
}

/*创建删除收支信息的方法,删除复选框勾选的记录*/
function removeCost(){
	var rcs = costGrid.getSelectionModel().getSelections();
	if(!rcs||rcs.length<1){
		Ext.Msg.alert("提示","请先选择要删除的行");
		return;
	}
	else{
		Ext.Msg.confirm("确认删除","请确认是否删除选中的项目支出条目?",function(btn){
			if(btn == "yes"){//选中"是"的按钮
				var ids = new Array();
				for (var i = 0; i < rcs.length; i++) {
					ids.push(rcs[i].get("id"));
				}
				//异步发请求
				Ext.Ajax.request({
					url:"deleteCosts.eva?doType=deleteCosts",
					method:"POST",
					params:{costIds:ids.join(",")},
					success:function(response,option){
						var result = Ext.util.JSON.decode(response.responseText);
						if (result.success) {
							Ext.Msg.alert("成功","选中的项目支出条目已成功删除!");
							costStore.rejectChanges();
							costStore.reload();
						}
					},
					failure:function(response,option){
						Ext.Msg.alert("失败","删除过程中发生错误!");
					}
				});
			}
		});
	}
}

注:

Ext中将数组转化为JSON字符串的方式:Ext.encode(array);

 

数组转json的数据如下:

[
  {
    "id": 1,
    "xmid": 1,
    "subject": "餐饮",
    "subjectId": 1,
    "planCost": 100,
    "actualCost": 200
  },
  {
    "id": 2,
    "xmid": 2,
    "subject": "医疗",
    "subjectId": 2,
    "planCost": 300,
    "actualCost": 500
  }
]

 

Servlet:处理传入的json数据,并保存:

if("updateProjectCost".equals(action)){
	ProjectCostDao costDao = new ProjectCostDao();
	String sData = request.getParameter("updateSets");
	List<ProjectCost> projectCosts = JSON.parseArray(sData, ProjectCost.class);//将Json字符串转化为集合
	boolean done = costDao.updateProjectCosts(projectCosts);
	String str=null;
	if(done){
		str="{success:true}";
	}else{
		str="{success:false}";
	}
	response.setContentType("text/html;charset=UTF-8");
	out=response.getWriter();
	out.print(str);		
	out.close();
	return;
}
注:FastJsonparseArray(jsonStr, T.class)方法可直接将符合设定的类的格式的JSON字符串转化成集合

 

Dao:保存数据

/**
 * 方法一:自己定义主键ID,对于新数据定义ID为-1,再根据ID判断是更新还是插入
 */
public boolean updateProjectCosts(List sets){
	boolean done = false;
	if(sets==null||sets.size()==0){
		return true;
	}
	Session s = null;
	try{
		s = HibernateUtil.getSession();
		s.beginTransaction();
		for(int i=0;i<sets.size();i++){
			ProjectCost cost = (ProjectCost) sets.get(i);
			int id = cost.getId();
			if(id<0){//新增
				s.save(cost);
			}else{
				ProjectCost initCost = (ProjectCost) s.get(ProjectCost.class, id);
				if (initCost != null) {
					initCost.setXmid(cost.getXmid());
					initCost.setCostSubject(cost.getCostSubject());
					initCost.setPlanCost(cost.getPlanCost());
					initCost.setActualCost(cost.getActualCost());
					s.flush();
				}
			}
		}
		s.getTransaction().commit();
		done = true;
	}catch(Throwable e) {
		logger.error(e.toString());
		HibernateUtil.endSession(s);
	}finally{
		HibernateUtil.endSession(s);
	}
	return done;
}

/**
 * 方法二:直接用saveOrUpdate,Hibernate会自动根据主键查询,有则更新,无则插入————更加方便快捷!
 */
public boolean updateProjectCosts(List<ProjectCost> projectCosts){
	boolean done = false;
	if(projectCosts==null||projectCosts.size()==0){
		return true;
	}
	Session s = null;
	try{
		s = HibernateUtil.getSession();
		s.beginTransaction();
		for(int i=0;i<projectCosts.size();i++){
			ProjectCost projectCost = projectCosts.get(i);
			s.saveOrUpdate(projectCost);
		}
		s.getTransaction().commit();
		done = true;
	}catch(Throwable e) {
		HibernateUtil.endSession(s);
	}finally{
		HibernateUtil.endSession(s);
	}
	return done;
}
自己根据ID判断:

 

直接用saveOrUpdate:


4.树面板TreePanel:注意查看下面标注的顺序

/*5.创建树形节点下拉选*/
//1.定义根节点
var costRoot = new Ext.tree.AsyncTreeNode({
	id:'tree-root',
	text:"经济科目",
	expanded:true,    //根节点默认展开(注意和TreePanel中的rootVisible:true的联系)
	draggable:false	  //根节点不可拖动
});
//2.定义节点数据加载器
var costLoader = new Ext.tree.TreeLoader({
	dataUrl:'getTree.base?doType=getPTreeByGrade&onlyValid=1',  //此处不是url,和Store的Proxy不同
	baseParams :{pid:''},
	baseAttrs:{uiProvider:Ext.tree.TreeCheckNodeUI}	//必须有该项,不然树节点无法出现选择框
});
//3.定义数据加载前触发方法
costLoader.on("beforeload",function(treeLoader,node){
	treeLoader.baseParams.pid = node.id;
},this);
//4.定义树形面板,用于显示数据
var costTree = new top.Ext.tree.TreePanel({    /**注意top!!!*/
	root:costRoot,      //根节点
	loader:costLoader,  //数据加载器
	autoScroll:true,    
	animate:false,
	enableDD:false,      //不允许子节点拖动
	rootVisible:true,    //显示根节点
	checkModel:"single", //复选框只能单选,多选为:multiple,级联:cascade
	onlyLeafCheckable:true,
	width:250,
	listeners:{"click":function(node){
		if(!node.isLeaf()){ 
	    	node.toggle(); //点击可展开可收缩
	    } 
	}}
});
//5.创建树节点窗口
var costTreeWin = new top.Ext.Window({    /**注意top!!!*/
	title:"经济科目",
	layout:"fit",
	closeAction:"hide",
	modal:true,
	width:250,
	height:250,
	items:costTree,
	buttons:[
		{
			text:"确定",
			handler:function(e){
				
				var node = costTree.getChecked();    //获取被选中的树节点
				if(!node || node.length < 1){
					Ext.Msg.alert("系统提示","请选择经济科目!");
					return;
				}
				var name = new Array();
				var value = new Array();
				for (var i = 0; i < node.length; i++) {
					name.push(node[i].text);
					value.push(node[i].id);
				}
				var data = selectedCostRow.data;    //获取选择的行的Record的Data数据对象
				data["subjectId"] = value.join();
				/*data["subject"]= name.join(); —— —— 此处用这种方式给触发域赋值出错!!!必须用下面的方式!!! */	
				costTrigger.setValue(name.join());
				costTreeWin.hide();
			}
		},{
			text:"取消",
			handler:function(){
				costTreeWin.hide();
			}
		}
	]
});

注意事项:

1.在可编辑表格面板中加触发域TriggerField,则关联的树面板TreePanel和树窗口Window在定义时必须用top置顶!!!否则无法在单元格中显示被选中的数据。

2.通过selectedRow.data获取选中的行所对应的Record的Data对象(注意该Data是Object对象!)

3.通过data["subjectId"] = value.join()方式,给该data对象中的各种属性赋值(注意改变的实际是Store的值!!

4.给TriggerField触发域占用的单元格赋值,必须用:costTrigger.setValue(name.join())

 

  此处若还是用data["subject"]    = name.join(),则会报错,原因尚未深究。


 

查询树节点的SQL:

 

SELECT *
  FROM (SELECT BM, MC, PID, ISLEAF, LEVEL
          FROM (SELECT BM, MC, PID, 0 AS ISLEAF
                  FROM BM_CONT
                 WHERE TABLE_BM = 'BM_GRADE'
                   AND YEAR = 2014 
                UNION
                SELECT TO_CHAR(ID) AS BM,
                       FILENO AS MC,
                       GID AS PID,
                       1 AS ISLEAF
                  FROM POLICY)
        CONNECT BY PRIOR BM = PID
         START WITH PID IS NULL)

 

查到的树节点的数据:

(具体数据请查看附件!)

 

5.窗口Window:

/*6.创建收支明细窗口*/
var costWin = new Ext.Window({
	title:"收支明细",
	frame:"fit",
	closeAction:"hide",
	modal:true,
	items:costGrid
});

 

 

6.点击显示窗口时传递需要的参数:

function showCostWin(xmid){
	Ext.getCmp("costXmid").setValue(xmid);
	costWin.show();
	costStore.baseParams.xmid = xmid;
	costStore.load();
}

 
     

 

图示:

 

 

 

 

  • 大小: 1.5 KB
  • 大小: 12.3 KB
  • 大小: 14.7 KB
  • 大小: 23.7 KB
  • 大小: 22.8 KB
  • 大小: 10.7 KB
  • 大小: 12.1 KB
  • 大小: 18.4 KB
  • 大小: 8.2 KB
  • 大小: 3.1 KB
  • 大小: 3 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics