Drag and drop data in Perspective

I want to give my end user the capability to drag data out of a container and into a different container.
As an example, I have a list of tasks in container A and I want to give the end user the ability to drag individual tasks from container A into containers B or C. I'd then update a database to reflect what container the task is in.

Any advice on how to approach this?

I used a different approach from drag and drop. Partly because of some touch screen PCs we have that don't really have a nice drag/drop feature or multi touch gestures.

I used tables and multiple selection option to give this feel. I select what rows that I want to move, then use some arrow buttons near the tables to move them to other 'containers'. I then use scripting in the background to update my databases accordingly.

1 Like

Thanks for that. Makes sense. It would be ideal to drag and drop, but I will look into this option as well.

There's currently no built-in components which allow for drag-and-drop. I too recommend you provide a way to select options and then use some sort of button-based interaction paradigm to use the selected options in some manner while removing them from pool 'A' and placing them in pool 'B' via scripting.

A Table would work when there are many options, but if you just expect a few to ever be selected at one time you could use a multi-select Dropdown.

I played around with a couple options, the button is the cleanest as the drag and drop while works its not clear to undersand as its not like the table row drags with the mouse.


Thanks for the answer.

@victordcq had a solution for this to allow drag drop. I'll dig up his post

1 Like

This one is something like that too, but i havent had the time to finish it yet. (combining full time work and evening school is quite draining)

got it updated

1 Like

Alternatively you could look at this Ignition exchange resource for inspiration DMC Drag and Drop Example. I could imagine also being able to get creative with some Perspective Messaging when clicking onto one container and releasing onto another container. But how the messaging could work depends greatly on how the views are configured.

The drag and drop in the exchange resource leverages the view canvas for this drag and drop behavior.

@victordcq

The table row drag and drop works very well out of the box, but I've managed to break it and I haven't figured out how it's breaking. If you use the pager and switch to page 2 it stops working. I see a similar phenomenon with my project. If the page loads with data (works great in the IDE, not so much in the browser) I can move rows. If the data changes in any way it breaks and stops working. I'm sure there's likely a simple fix, but I haven't been able to figure it out yet.

which one are you using? i have a couple of versions running around...

Hmmm, good question. It's from 2023.

This is from the resource.json file.

"timestamp": "2023-01-26T10:29:57Z"
"lastModificationSignature": "83569c9745b13dbed670550429074f9f96d8c6b454781b2aadb0024e8bf7dad0"

i mean which post did you get the file from?

It's a couple rows up on this thread

ah yes this does not use the mutation observer yet

this should fix that, replace the markdown binding script with this

	#make the propName the key to write too in the view.custom 
	propName = "rowDroppedData"
	code =  """<img style='display:none' src='/favicon.ico' onload=\"
		const view = [...window.__client.page.views._data.values()].find(view => view.value.mountPath == this.parentNode.parentNode.parentNode.getAttributeNode('data-component-path').value.split('.')[0]).value; 
		function ondrop(ev) {
			ev.preventDefault(); 
			const draggedId = ev.dataTransfer.getData('text');
			const droppedId = this.getAttribute('data-row-id'); 
			view.custom.write('"""+propName+"""',{'draggedId':draggedId,'droppedId':droppedId});
		};
		function ondragstart(ev){
			
			ev.dataTransfer.setData('text', ev.target.getAttribute('data-row-id'));
		};
		function ondragover(ev){
			ev.preventDefault();
		};
		
		const callbackTable = (mutationList, observer) => {
		document.querySelectorAll('.tr-group.ia_table__rowGroup').forEach(e => {
					e.setAttribute('draggable',true);
					e.ondragstart = ondragstart;
					e.ondragover = ondragover;
					e.ondrop = ondrop;
				});	
		};
				
			
									
		const observerTable = new MutationObserver(callbackTable); 
		const tables = document.querySelectorAll('.ia_tableComponent .tb.ia_table__body');
		tables.forEach(table => observerTable.observe(table, { attributes: false, childList: true, subtree: true }));	
		document.querySelectorAll('.tr-group.ia_table__rowGroup').forEach(e => {
						e.setAttribute('draggable',true);
						e.ondragstart = ondragstart;
						e.ondragover = ondragover;
						e.ondrop = ondrop;
					});		
				
	\"></img>""".replace("\n", "").replace("\t", "")
	return code
	
3 Likes

that's a beautiful thing

2 Likes