# Dragging rows in Perspective Table

**URL:** <https://forum.inductiveautomation.com/t/dragging-rows-in-perspective-table/68922>\
**Category:** Ignition\
**Tags:** perspective\
**Created:** [January 23, 2023, 5:01pm UTC](https://forum.inductiveautomation.com/t/dragging-rows-in-perspective-table/68922 "2023-01-23T17:01:05Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![jasoncoope](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/jasoncoope/32/18674_2.png) [@jasoncoope](https://forum.inductiveautomation.com/u/jasoncoope)\
**Post date:** [January 23, 2023, 5:01pm UTC](https://forum.inductiveautomation.com/t/dragging-rows-in-perspective-table/68922/1 "2023-01-23T17:01:05Z")

</div>

Has anyone figured out how to drag rows around in a perspective table? Need user to be able to change the sort order of rows that will then be saved in the database.

---

<div class="post-metadata">

**Author:** ![deon.korb](https://avatars.discourse-cdn.com/v4/letter/d/8c91f0/32.png) [@deon.korb](https://forum.inductiveautomation.com/u/deon.korb)\
**Post date:** [January 23, 2023, 5:12pm UTC](https://forum.inductiveautomation.com/t/dragging-rows-in-perspective-table/68922/2 "2023-01-23T17:12:13Z")

</div>

I don't think this is possible, but I'd love to know. I have a perfect application for it

---

<div class="post-metadata">

**Author:** ![nicoli.liedtke](https://avatars.discourse-cdn.com/v4/letter/n/ee59a6/32.png) [@nicoli.liedtke](https://forum.inductiveautomation.com/u/nicoli.liedtke)\
**Post date:** [January 24, 2023, 10:56pm UTC](https://forum.inductiveautomation.com/t/dragging-rows-in-perspective-table/68922/3 "2023-01-24T22:56:41Z")

</div>

Have once applied this functionality by adding a view to each row of the table that included and icon of an up and down arrow. Clicking an arrow would send a perspective message to the table that would change the order of its data by indexing the row up or down 1.

---

<div class="post-metadata">

**Author:** ![deon.korb](https://avatars.discourse-cdn.com/v4/letter/d/8c91f0/32.png) [@deon.korb](https://forum.inductiveautomation.com/u/deon.korb)\
**Post date:** [January 25, 2023, 6:23am UTC](https://forum.inductiveautomation.com/t/dragging-rows-in-perspective-table/68922/4 "2023-01-25T06:23:52Z")

</div>

> [@nicoli.liedtke](#):
>
> g a view to each row of the table that included and icon of an up and down arrow. Clicking an arrow would send a perspective message to the table that would change the order of its data by indexing the row up or down 1.

I did the same, but implemented with a flex repeater. I really would like a draggable list, just like a playlist on modern music services

---

<div class="post-metadata">

**Author:** ![nminchin](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/nminchin/32/6911_2.png) [@nminchin](https://forum.inductiveautomation.com/u/nminchin)\
**Post date:** [January 25, 2023, 9:15am UTC](https://forum.inductiveautomation.com/t/dragging-rows-in-perspective-table/68922/5 "2023-01-25T09:15:10Z")

</div>

Maybe @victordcq knows if possible with magic hacks?

---

<div class="post-metadata">

**Author:** ![victordcq](https://avatars.discourse-cdn.com/v4/letter/v/f6c823/32.png) [@victordcq](https://forum.inductiveautomation.com/u/victordcq)\
**Post date:** [January 25, 2023, 9:25am UTC](https://forum.inductiveautomation.com/t/dragging-rows-in-perspective-table/68922/6 "2023-01-25T09:25:51Z")

</div>

heh would require some tinkering, but ive done a drag and drop before  
You could make a view for the first column but isntead with the arrow use something like this...

> [@Perspective Mouse Click & Drag](https://forum.inductiveautomation.com/t/perspective-mouse-click-drag/28583/27):
>
> Soooo.... i was playing around a bit and i found something to inject js in perspective. I know i know crazy_face Its kinda terrible and requires some knowlegde about the perspective react props... But this seems like it would fit here. A little demo, not to complex for drag and drop. Im writing it to a sessionprop, seems to be easier than trying to find the view props. [dndjsinject.zip](https://forum.inductiveautomation.com/uploads/short-url/k9uW6F1ZYMhCSZY1l161wy5UWue.zip) (7.5 KB) @nader.chinichian

i can play around with this a bit more tmw 😉 Might be possible to not require a view/column and just make the whole row draggable but ill have to take a deeper look

---

<div class="post-metadata">

**Author:** ![pascal.fragnoud](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pascal.fragnoud/32/24728_2.png) [@pascal.fragnoud](https://forum.inductiveautomation.com/u/pascal.fragnoud)\
**Post date:** [January 25, 2023, 10:53am UTC](https://forum.inductiveautomation.com/t/dragging-rows-in-perspective-table/68922/7 "2023-01-25T10:53:32Z")

</div>

Seems to me like it would be easier with a flex repeater...

---

<div class="post-metadata">

**Author:** ![victordcq](https://avatars.discourse-cdn.com/v4/letter/v/f6c823/32.png) [@victordcq](https://forum.inductiveautomation.com/u/victordcq)\
**Post date:** [January 26, 2023, 10:30am UTC](https://forum.inductiveautomation.com/t/dragging-rows-in-perspective-table/68922/8 "2023-01-26T10:30:51Z")

</div>

ah it was easy, ignition puts its row id in a data atrribute so it was easy to read.

@jasoncoope  
[dragtable.zip](https://forum.inductiveautomation.com/uploads/short-url/AvXF36eUYUY52tcHnheVhENIotA.zip) (27.7 KB)

copy the markdown  
and add in a custom property on the view  
you probably will have to adapt the onchange script in the view.custom element to your needs.

sometimes the columns seem to move around too when you drag a row... not sure why or how to prevent that... probably clashing with the other drag events on the table xd  
**edit** :  
ahah, turn this off too, well unless you dont mind  
 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/9/0/90dfe89240383875487f49601c320acd76ed1493.png)

**update:** a fix for unvirtualised tables and tables with multple pages... using the js mutation observer:

```auto
	#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 .t.ia_table > .tb');
		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
	

```

(also just gona link this to my other jsinjects post

> [@Javascript inject in Perspective... have fun](https://forum.inductiveautomation.com/t/javascript-inject-in-perspective-have-fun/65805/5):
>
> Gonna try to keep this topic updated with all my cool injectings stuck_out_tongue Version 8.1.22 svg clicker wink

---

<div class="post-metadata">

**Author:** ![jasoncoope](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/jasoncoope/32/18674_2.png) [@jasoncoope](https://forum.inductiveautomation.com/u/jasoncoope)\
**Post date:** [February 7, 2023, 4:17am UTC](https://forum.inductiveautomation.com/t/dragging-rows-in-perspective-table/68922/9 "2023-02-07T04:17:25Z")

</div>

Outstanding! Just need to figure out how this works. Thanks for your help here!

---

<div class="post-metadata">

**Author:** ![Gavin\_Tipker](https://avatars.discourse-cdn.com/v4/letter/g/f475e1/32.png) [@Gavin\_Tipker](https://forum.inductiveautomation.com/u/Gavin_Tipker)\
**Post date:** [May 2, 2023, 2:00pm UTC](https://forum.inductiveautomation.com/t/dragging-rows-in-perspective-table/68922/10 "2023-05-02T14:00:44Z")

</div>

I love this! This was super easy to implement and very straight forward. I did notice that if you're populating your table data from a named query you have to select to bring it in as a json and not a dataset to get this to work.

Another thing, do you think you could set this up to be able to drag a row from one table to another if they have the same column structure? Like say if I had two tables side by side and they both had "Name" and "Address" as the columns? @victordcq

---

<div class="post-metadata">

**Author:** ![victordcq](https://avatars.discourse-cdn.com/v4/letter/v/f6c823/32.png) [@victordcq](https://forum.inductiveautomation.com/u/victordcq)\
**Post date:** [May 2, 2023, 2:24pm UTC](https://forum.inductiveautomation.com/t/dragging-rows-in-perspective-table/68922/11 "2023-05-02T14:24:34Z")

</div>

> [@Gavin\_Tipker](#):
>
> you have to select to bring it in as a json and not a dataset to get this to work.

ah yes, its a bit anonying to change positions in js for a dataset

> [@Gavin\_Tipker](#):
>
> Like say if I had two tables side by side and they both had "Name" and "Address" as the columns?

yes that would be possible, but i dont really have time to set this up any time soon. Maybe i got time somewhere next month?  
you'll have to combine this with the second script i put here

> [@Perspective Scheduler - Drag and Drop From Table](https://forum.inductiveautomation.com/t/perspective-scheduler-drag-and-drop-from-table/71853/12):
>
> yes you can setup a mutation observer that triggers on domchanges ive done something similar here: i'll fix up the script i have in a bit edit: here you go! a table , a schedule and the markdown are in here, with the dragdrop in de markdown and an (example of) AddEvent in de schedule. [tabledropschedule.zip](https://forum.inductiveautomation.com/uploads/short-url/vraW8MysI6UtTLmks7yMcZEDSM8.zip) (12.6 KB)

things to change in the second script are the query selectors for the scheduler to the one of the table you want to drop in (you should add in a domId to make this easier)

and ofc the ondrop event to instead change its data (or send a message or something)

---

<div class="post-metadata">

**Author:** ![Gavin\_Tipker](https://avatars.discourse-cdn.com/v4/letter/g/f475e1/32.png) [@Gavin\_Tipker](https://forum.inductiveautomation.com/u/Gavin_Tipker)\
**Post date:** [May 2, 2023, 2:33pm UTC](https://forum.inductiveautomation.com/t/dragging-rows-in-perspective-table/68922/12 "2023-05-02T14:33:13Z")

</div>

Thanks for the info! I'll see if I can get this working. If I do I'll let you know.

---

<div class="post-metadata">

**Author:** ![victordcq](https://avatars.discourse-cdn.com/v4/letter/v/f6c823/32.png) [@victordcq](https://forum.inductiveautomation.com/u/victordcq)\
**Post date:** [May 2, 2023, 2:50pm UTC](https://forum.inductiveautomation.com/t/dragging-rows-in-perspective-table/68922/13 "2023-05-02T14:50:20Z")

</div>

feel free to show you trials too, the code in the markdown that is.  
i should have some time along the week to review that, just not to test it all myself

---

<div class="post-metadata">

**Author:** ![victordcq](https://avatars.discourse-cdn.com/v4/letter/v/f6c823/32.png) [@victordcq](https://forum.inductiveautomation.com/u/victordcq)\
**Post date:** [May 3, 2023, 9:07am UTC](https://forum.inductiveautomation.com/t/dragging-rows-in-perspective-table/68922/14 "2023-05-03T09:07:42Z")

</div>

mh it shouldnt be that difficult tbh,

just add a domId to both tables in perspective.

in the ondragstart, change the setData to include the domId of the origin in there (you'll need to use a strinigfied json as it only can transfer text. `JSON.stringify(myObj)`  
in the onDrop, extract the domId and draggedId from the stringified json ev.dataTransfer.getData('text')  
also find the domId of the target here `JSON.parse(text)`  
and add both the origin and target domId to the view.custom.write.

from there its adjusting the python script, shouldnt be to hard if you match the domIds with the component names

---

<div class="post-metadata">

**Author:** ![Gavin\_Tipker](https://avatars.discourse-cdn.com/v4/letter/g/f475e1/32.png) [@Gavin\_Tipker](https://forum.inductiveautomation.com/u/Gavin_Tipker)\
**Post date:** [May 3, 2023, 7:34pm UTC](https://forum.inductiveautomation.com/t/dragging-rows-in-perspective-table/68922/15 "2023-05-03T19:34:17Z")

</div>

I was able to get it to work. Had to do some extra work to allow it to drop into an empty table. I still need to figure out how to drop on to a table in the white space where there isn't any rows but wanted to update you on my progress from today.

```auto
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; 
	async function ondrop(ev) {
		ev.preventDefault(); 
		const draggedData = ev.dataTransfer.getData('text');
      	const obj = JSON.parse(draggedData);
	  	const draggedId = obj.draggedId;
      	const draggedTable = obj.domID;	
  	    const droppedId = this.getAttribute('data-row-id');
  	    const droppedTable = this.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode.getAttribute('id'); 
  	    const droppedTableEmpty = this.classList.contains('empty-data-source');
  	    const droppedTableEmptyID = this.parentNode.parentNode.parentNode.parentNode.getAttribute('id');
  	    view.custom.write('"""+propName+"""',{'draggedId':draggedId,'droppedId':droppedId,'draggedTable':draggedTable,'droppedTable':droppedTable,'droppedTableEmptyID':droppedTableEmptyID,'droppedTableEmpty':droppedTableEmpty});
		await sleep(500);
		resetTables();
	};
	function ondragstart(ev){
		resetTables();
		ev.dataTransfer.setData('text', JSON.stringify({draggedId:ev.target.getAttribute('data-row-id'), domID:ev.target.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode.id}));
	};
	function ondragover(ev){
		ev.preventDefault();
	};
	
    function resetTables(){
        document.querySelectorAll('.tr-group.ia_table__rowGroup').forEach(e => {
            e.setAttribute('draggable',true);
            e.ondragstart = ondragstart;
            e.ondragover = ondragover;
            e.ondrop = ondrop;
        });	
        
        document.querySelectorAll('.empty-data-source').forEach(e => {
                e.setAttribute('draggable',true);
                e.ondragstart = ondragstart;
                e.ondragover = ondragover;
                e.ondrop = ondrop;
            });	
    };
    
        function sleep(ms) {
            return new Promise(resolve => setTimeout(resolve, ms));
        }
    
	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", "")

```

```auto
if currentValue.value["droppedTableEmpty"].value:
	if int(currentValue.value["draggedId"].value) > -1:
		DraggedTable=self.getChild("rowDroppedData").getChild(currentValue.value["draggedTable"].value).props.data
		DroppedTable=self.getChild("rowDroppedData").getChild(currentValue.value["droppedTableEmptyID"].value).props.data
		DroppedTable.append(DraggedTable.pop(int(currentValue.value["draggedId"].value)))
else:
	if int(currentValue.value["droppedId"].value) > -1 and int(currentValue.value["draggedId"].value) > -1:
		DraggedTable=self.getChild("rowDroppedData").getChild(currentValue.value["draggedTable"].value).props.data
		DroppedTable=self.getChild("rowDroppedData").getChild(currentValue.value["droppedTable"].value).props.data
		if currentValue.value["draggedTable"].value == currentValue.value["droppedTable"].value:
			DroppedTable.insert(int(currentValue.value["droppedId"].value), DroppedTable.pop(int(currentValue.value["draggedId"].value)))
		else:
			DroppedTable.insert(int(currentValue.value["droppedId"].value), DraggedTable.pop(int(currentValue.value["draggedId"].value)))
self.custom.rowDroppedData.draggedId = -1
self.custom.rowDroppedData.droppedId = -1
self.custom.rowDroppedData.droppedTable = -1
self.custom.rowDroppedData.draggedTable = -1
self.custom.rowDroppedData.droppedTableEmpty = False
self.custom.rowDroppedData.droppedTableEmptyID = -1

```

---

<div class="post-metadata">

**Author:** ![victordcq](https://avatars.discourse-cdn.com/v4/letter/v/f6c823/32.png) [@victordcq](https://forum.inductiveautomation.com/u/victordcq)\
**Post date:** [May 4, 2023, 6:09am UTC](https://forum.inductiveautomation.com/t/dragging-rows-in-perspective-table/68922/16 "2023-05-04T06:09:37Z")

</div>

do not use sleep, use the mutation observer, i had updated the post a few days ago with the mutation observer in it, it will trigger the callback funciton anytime the content inside it changes, you might need to use a higher level selector though for the `const tables` because of the empty rows, i didnt test that (so try without the` > tb`)

> [@victordcq](#):
>
> ```auto
> 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 .t.ia_table > .tb');
> 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;
> });	
> 
> ```

you can use the queryselector  
`.ia_tableComponent .t.ia_table > .tb` for the empty table and the empty space below the rows.  
it might double trigger an ondrop event though  
in which case you will need to add this to the ondrop function of the rows

```auto
ev.stopPropagation();

```

you should use a seperate ondrop function for the empty ones, as the id will not be found the same and there will be no data-row-id

and you dont need this in the empty row ones, so they cant accidently drag the whole table

```auto
e.setAttribute('draggable',true);
                e.ondragstart = ondragstart;

```

> [@Gavin\_Tipker](#):
>
> ```auto
> document.querySelectorAll('.empty-data-source').forEach(e => {
> e.setAttribute('draggable',true);
> e.ondragstart = ondragstart;
> e.ondragover = ondragover;
> e.ondrop = ondrop;
> });	
> 
> ```

---

<div class="post-metadata">

**Author:** ![Gavin\_Tipker](https://avatars.discourse-cdn.com/v4/letter/g/f475e1/32.png) [@Gavin\_Tipker](https://forum.inductiveautomation.com/u/Gavin_Tipker)\
**Post date:** [May 4, 2023, 12:17pm UTC](https://forum.inductiveautomation.com/t/dragging-rows-in-perspective-table/68922/17 "2023-05-04T12:17:29Z")

</div>

Okay, I think I have it all working now.

```auto
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(); 
        ev.stopPropagation();
		const draggedData = ev.dataTransfer.getData('text');
      	const obj = JSON.parse(draggedData);
	  	const draggedId = obj.draggedId;
      	const draggedTable = obj.domID;	
  	    const droppedId = this.getAttribute('data-row-id');
	    const droppedTable = this.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode.getAttribute('id');
        const droppedEmpty = this.classList.contains('tb');
        const droppedEmptyTable = this.parentNode.parentNode.parentNode.getAttribute('id');
        view.custom.write('"""+propName+"""',{'draggedId':draggedId,'droppedId':droppedId,'draggedTable':draggedTable,'droppedTable':droppedTable,'droppedEmptyTable':droppedEmptyTable,'droppedEmpty':droppedEmpty});
	};
	function ondragstart(ev){
        refreshEmptyTables();
		ev.dataTransfer.setData('text', JSON.stringify({draggedId:ev.target.getAttribute('data-row-id'), domID:ev.target.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode.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 .t.ia_table > .tb');
        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;
        });
        
        function refreshEmptyTables(){
            document.querySelectorAll('.ia_tableComponent .t.ia_table > .tb').forEach(e => {
                e.ondragover = ondragover;
                e.ondrop = ondrop;
            });
        }
    
\"></img>""".replace("\n", "").replace("\t", "")
return code

```

I had to add the refreshEmptyTables function because it seems that when the page first loads all the datasets are empty until they load in which was causing none of the rows to be draggable if I ran that at page load.

```auto
if currentValue.value["droppedEmpty"].value:
	if int(currentValue.value["draggedId"].value) > -1:
		if currentValue.value["droppedEmptyTable"].value == currentValue.value["draggedTable"].value:
			DraggedTable=self.getChild("rowDroppedData").getChild(currentValue.value["draggedTable"].value).props.data
			DraggedTable.append(DraggedTable.pop(int(currentValue.value["draggedId"].value)))
		else:
			DraggedTable=self.getChild("rowDroppedData").getChild(currentValue.value["draggedTable"].value).props.data
			DroppedTable=self.getChild("rowDroppedData").getChild(currentValue.value["droppedEmptyTable"].value).props.data
			DroppedTable.append(DraggedTable.pop(int(currentValue.value["draggedId"].value)))
else:
	if int(currentValue.value["droppedId"].value) > -1 and int(currentValue.value["draggedId"].value) > -1:
		DraggedTable=self.getChild("rowDroppedData").getChild(currentValue.value["draggedTable"].value).props.data
		DroppedTable=self.getChild("rowDroppedData").getChild(currentValue.value["droppedTable"].value).props.data
		if currentValue.value["draggedTable"].value == currentValue.value["droppedTable"].value:
			DroppedTable.insert(int(currentValue.value["droppedId"].value), DroppedTable.pop(int(currentValue.value["draggedId"].value)))
		else:
			DroppedTable.insert(int(currentValue.value["droppedId"].value), DraggedTable.pop(int(currentValue.value["draggedId"].value)))
self.custom.rowDroppedData.draggedId = -1
self.custom.rowDroppedData.droppedId = -1
self.custom.rowDroppedData.droppedTable = -1
self.custom.rowDroppedData.draggedTable = -1
self.custom.rowDroppedData.droppedEmpty = False
self.custom.rowDroppedData.droppedEmptyTable = -1

```

---

<div class="post-metadata">

**Author:** ![nminchin](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/nminchin/32/6911_2.png) [@nminchin](https://forum.inductiveautomation.com/u/nminchin)\
**Post date:** [May 5, 2023, 12:27am UTC](https://forum.inductiveautomation.com/t/dragging-rows-in-perspective-table/68922/18 "2023-05-05T00:27:31Z")

</div>

I wish I understood even just a few lines of this code ☹ I'll get time one of these days to look at javascript. But this sounds cool!

I need to allow operators to select multiple table rows with only a mouse, no keyboard. Reckon I can do that with js instead of hacking a checkbox into a new column?  
I don't really know the mechanics I would use. Maybe click to select/deselect, then a button to unselect all?

---

<div class="post-metadata">

**Author:** ![victordcq](https://avatars.discourse-cdn.com/v4/letter/v/f6c823/32.png) [@victordcq](https://forum.inductiveautomation.com/u/victordcq)\
**Post date:** [May 5, 2023, 9:38am UTC](https://forum.inductiveautomation.com/t/dragging-rows-in-perspective-table/68922/19 "2023-05-05T09:38:09Z")

</div>

like a button that mimicks you holding ctlr?

---

<div class="post-metadata">

**Author:** ![nminchin](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/nminchin/32/6911_2.png) [@nminchin](https://forum.inductiveautomation.com/u/nminchin)\
**Post date:** [May 5, 2023, 9:42am UTC](https://forum.inductiveautomation.com/t/dragging-rows-in-perspective-table/68922/20 "2023-05-05T09:42:30Z")

</div>

That could be one way, toggle it on off. Is that doable?

[Next page](https://forum.inductiveautomation.com/t/dragging-rows-in-perspective-table/68922.md?page=2)
