拖动排序问题

拖动排序

Ext.data.NodeInterface 这个对象还树形treepanel是很重要的。store里面存放的都是这个。展开、Expaned或者折叠。

相关知识

  • 快速查找相关的工具,比如grid插件,通过这个关键字 grid.plugin
  • DragDrop源码,这个插件源码非常简单,里面有个重要的函数,onViewRender。其中有一行代码:
ownerGrid.relayEvents(view, ['beforedrop', 'drop']);

所以从Ext.mixin.Observable中查找到这个relayEvents函数,主要功能是用来传递事件。即将插件的触发的事件传递到grid表格。

问题分析

从后端来说,为了满足排序,必须额外使用一个字段辅助排序。但是增加这个字段order,给一个默认值,比如100,又不会增加额外的编程难度。(排序,并不是更换两个id)。总结:目前还是没有好的想法,最简单粗暴的处理方式就是,前端直接将一个分组内的排序,告诉后端,后端直接进行遍历,从0开始增加1。(字段默认也是从0开始)。但是这样的问题是,业务处理代码简单,但是数据库增加了不必要的操作。(暂定此方法。)

从前端来说,需要支持拖拽排序。从网上找到了Ext的这个插件的用法。但是细节还不清楚。参见文章,代码基本可用。

核心代码:

viewConfig: {
	plugins: {
		ptype: "gridviewdragdrop",
		dragText: "可用鼠标拖拽进行上下排序"
	}
},

实现Grid行的上下移动

Ext.onReady(function() {
	var proStore = Ext.create("Ext.data.Store", {
		fields: ["code", "name", "num"],
		data: [
			["#001", "iPhone6", 100],
			["#002", "iPhone6 Plus", 80],
			["#003", "Mi Note4", 99],
			["#004", "Galaxy S6", 75],
			["#005", "Smartisan T2", 68]
		]
	});
	
	Ext.create("Ext.grid.Panel", {
		title: "可用鼠标拖拽行数据的Grid",
		width: 400,
		margin: 10,
		border: true,
		store: proStore,
		columns: [{
			text: "产品编号",
			dataIndex: "code",
			flex: 1
		}, {
			text: "产品名称",
			dataIndex: "name",
			flex: 1
		}, {
			text: "产品数量",
			dataIndex: "num",
			flex: 1
		}],
		viewConfig: {
			plugins: {
				ptype: "gridviewdragdrop",
				dragText: "可用鼠标拖拽进行上下排序"
			}
		},
		renderTo: Ext.getBody()
	});
});

实现多个Grid之间的相互移动

要让行数据可在多个Grid之间相互移动,只需在Grid引用Ext.grid.plugin.DragDrop插件时,为其指定同一个组名,表明它们属于同一组,可相互移动。

当然,前提是这些Grid使用的Model类应该一致,即表格字段应该一致。

viewConfig: {
	plugins: {
		ptype: "gridviewdragdrop",
		ddGroup: "DrapDropGroup"
	}
}

开始处理代码

版本说明:使用的是Ext5.1.0.107版本。使用6.5中的手册写法略有不同。

问题

  • 插件的事件无法监听到。解决办法,写到viewConfig的listeners中。
//备注:me指代的是grid。另外写在grid的listeners也没有反应。
me.on('beforedrop',function(node, data, overModel, dropPosition, dropHandlers) {
  • 找到排序后的数据

只是简单的跟了一个位置before、after。通过store.getData获取到数据。

  • 理解事件传递的值,解决了判断,该节点能不能拖拽到节点

当前拖动的记录:data.records[0]
目标的记录:overModel
相对位置关系:dropPosition

  • 父节点,默认只展开一级。代码写了,却没有效果。

  • 显示优化问题

如果重新加载数据,则数据全部重新刷新了。原来展开的,折叠住了。如果不刷新吧,那么拖动末个节点,显示异常。

  • 展开节点问题

必须使用Ext.data.NodeInterface提供的expand、collapse等方法。而不能通过record.set方法来实现。注意跟checked的区别。

/************
	2019/4/2
	只展开顶级节点
************/
expandTopRecord:function(){
	var me=this;
	var root = me.store.getRoot();
	Ext.Array.each(root.childNodes,function(node){
		//注意不能使用//node.set('expanded',false);
		node.collapse();
	});
},
//官方手册
Ext.grid.plugin.DragDrop
drop ( node, data, overModel, dropPosition, eOpts ) 

// 官方例子 build/examples/kitchensink/?classic#dd-grid-to-grid
onDropGrid1: function (node, data, dropRec, dropPosition) {
        this.onDrop(dropRec, data.records[0], dropPosition, 'Drag from right to left');
},
  • 范围

简单的处理逻辑

//me.getdog();
var view=me.getView();
view.on('beforedrop',function(node, data, overModel, dropPosition, dropHandlers) {
	// Defer the handling
	//dropHandlers.wait = true;
	
	//1、判断当前节点,
	//一级节点,则进行折叠
	//否则,停止拖动前进行判断,如果合适,则允许放入。
	
	
	/*Ext.MessageBox.confirm('Drop', 'Are you sure', function(btn){
		if (btn === 'yes') {
			dropHandlers.processDrop();
		} else {
			dropHandlers.cancelDrop();
		}
	});*/
});
view.on('drop',function(node, data, overModel, dropPosition, eOpts) {
	//获取排序后的数据console.log(me.store.getData());
	//根据当前节点ParentID,过滤出该组的数据。
	//然该组数据发送致后台
});

正式代码


var view=me.getView();
//注意,使用这种方式进行监听
view.on('beforedrop',function(node, data, overModel, dropPosition, dropHandlers,eOpts) {
	// Defer the handling
	dropHandlers.wait = true;
	var curRd=data.records[0];
	//判断当前节点,是否可移动,同一组内可移动。
	if(curRd.get('ParentID')!=overModel.get('ParentID')){
		dropHandlers.cancelDrop();
	}else{
		dropHandlers.processDrop();
	}
});
view.on('drop',function(node, data, overModel, dropPosition, eOpts) {
	//获取排序后的数据console.log(me.store.getData());
	var curRd=data.records[0];
	var pid=curRd.get('ParentID');
	var Rds=me.store.getData().items;
	//根据当前节点ParentID,过滤出该组的数据。
	var fRds=Ext.Array.filter(Rds,x=>x.get('ParentID')==pid);
	var ids=Ext.Array.map(fRds,x=>x.get('GroupID'));
	//然该组数据发送致后台
	Ext.Ajax.request({
		url: '/admin/device/Terminal/orderterminalgroup/', 
		params: {'ids': Ext.encode(ids)}, 
		method: 'POST', 
		success: function(response, option)
		{
			//记录当前折叠状态
			me.updateExpandIds();
			//更新树木,避免显示乱问题
			me.store.reload();
			//但是如果更新了,节点展开的就关闭了
		},
		failure: function(){}
	});
});

//node.set('expanded',false); 除了数据加载阶段可用
//其他阶段不可用,应使用expand函数等

/************
	2019/4/2
	记录展开的id。此方法不是递归的,所以呢,只能处理简一层。
************/
updateExpandIds:function(){
	var me=this;
	var root = me.store.getRoot();
	me.expandIds=[];
	Ext.Array.each(root.childNodes,function(node){
		if(node.data.expanded===true){
			me.expandIds.push(node.data.GroupID);
		}
	});
},

//在store.load时,更新expand状态
Ext.Array.each(records,function(rd){
	if(Ext.Array.indexOf(me.expandIds,rd.get('GroupID'))!==-1){
		rd.set({expanded:true});//此时可用,因为树还没有重新渲染
	}
});