Cutting Edge Dragable List - Python Only

Hi There,

There are several forum posts of drag and drop functionality:

As well as some working examples:

This example uses the https://muuri.dev/ library. And with the help of anvil.js Anvil Docs | JavaScript this is implemented without any javascript.

captured (1)

How it works:

  1. Go to Native Libraries and add this Line:
    <script src="https://cdn.jsdelivr.net/npm/muuri@0.9.3/dist/muuri.min.js"></script>

  2. Add those two anvil roles to the Assets:
    Muuri Drag and Drop constists of a grid (which is more or less the container that enables dragging) and items which can be dragged around.

They need special styling, thus we use Anvil Roles to implement that.

 .anvil-role-grid {
  position: relative;
  overflow: hidden;
}

.anvil-role-item {
  display: block;
  position: absolute;
  margin: 2px;
  z-index: 1;
}
.anvil-role-item.muuri-item-dragging {
  z-index: 3;
}
.anvil-role-item.muuri-item-releasing {
  z-index: 2;
}
.anvil-role-item.muuri-item-hidden {
  z-index: 0;
}
  1. The rest is all standard python/anvil stuff.

Disclaimer
On every update list i destroy and recreate the grid object.
This is not the intended way - but I couldn’t get it to work otherwise and it didn’t bother me to much.

Feel free to ask, reuse and help improve this drag and drop code for anvil.

Greetings, Mark

22 Likes

This is awesome! Keep up with the great work.

~ Beckett

In the demo, I hit a bug where if my window is too wide, the items distribute among two columns (and the dragging doesn’t work for the second column):

The issue resolves if you use a fixed width container (via FlowPanel):
https://anvil.works/build#clone:C2M7GOOXDTZHNM72=P6BEUDTYGBFZDGWZM3O4TEOM

@mark.breuss Have you developed this any further? For instance, have you created a way to access the changed order of the list after the drag and drop? It’s hard for me to see how one could use the List component as it is.

I needed to get the order of the list after the drag and drop, as hugetim was talking about.

Here is a clone link with one (not particularly good) way of doing this. Basically I added a hidden label capturing the text I wanted and assign that a new ‘dragresult’ role. We call grid.synchronize per Muuri documentation to make sure the HTML DOM order is consistent with the order we see and then use jQuery to find the dragresult elements, extracting the text from that hidden label.

https://anvil.works/build#clone:LJRAXEFNINOA2Z6O=XQ562AX4Z3UV7BQNCMS7G4FH

It seems like this should be possible using the grid.getItems method but you’d still need to use jQuery or something to get to the right HTML element. So I just query on that dragresult role directly.

Ideally this would return the Anvil Python elements in order but this implementation is a ways from that!

2 Likes

Good Morning @danbolinson @hugetim

Its been quite busy lately thus I have not come around to share a more updated Version.

However I’ve put together a custm component that should meet your needs.
https://anvil.works/build#clone:BWY2CQ6QCNHO5DE3=PUQXHHNMUQGEBHRN3CSFBLEM

You can give it a list of dicts, which are then displayed as a draggable list.
With the method get_sort() the component returns the sorted result.
You should be able to figure out the rest via the code pretty quickly.

Use the clone the link above and give it a try!

Greetings Mark

3 Likes

Hi Mark,
that is a great work you have done. Wonder if you can help me with that.


Aaron

Hi @Aaron,

You could do this with Drag and Drop - however this is quite complicated. Or better said I havent found a simple way.

If you can get away without drag and drop I’d suggest something like this:

https://anvil.works/build#clone:PT7C34SWBUZDBASR=OEPFAFGDBQ5QCHCCV24LXWMY
Attention though: This example is no production ready code, rather a quick showcase to get you startet (Don’t have the time for more to be honest). Check out @stefano.menci TDD best practices for clean code and structure.

Still - hope this example helps you along!

Grüße aus Vorarlberg :wink:

Mark

2 Likes

@mark.breuss , I’ve had great benefit of the work you’ve shared on the dragable list. Thanks!

I’m using this in my app, and I think it could be worth sharing the version I’ve ended up at that started from your demo app. It has events and works with arbitrary components.

https://anvil.works/build#clone:CCQPZ67AVYACIEZM=TOU3IKY3XLHLFL2R3QUPAPOF

1 Like

@stein
Glad it was helpful to you!

Thanks for sharing - looks nice :+1:

And to keep the train going, I made my own modifications so I could more easily add and remove items from the list when it’s used as a custom component.

I also used Anvil Extras Utils module to inject the Muuri grid CSS that one of y’all added because for some reason it wasn’t being respected when I used it as a Custom component in a different app.

https://anvil.works/build#clone:MIEZJN7FAWUELZUB=NQNFHQ56OWT6GXUTVYGSEMP5

Thanks so much for building this so I only had to make a few mods to get it working for my purposes @mark.breuss @stein !

Update: I also added an event for when the list changes (from adding or removing an item or from changing the order) that can be called on instances of the draggable list.

4 Likes

@duncan_richards12 Awesome - great job!

Its astonishing to see how the component has evolved through the community over the 14 months since posting the first version :muscle:

3 Likes

This is very useful. Thank you for that!

1 Like

Doing some modifications to your app, trying to make deleting items more user friendly.

Still buggy, but I’m working on it. See the clone link if you wanna take a whack at it.

fun

https://anvil.works/build#clone:AI5RMMERQH33RUE7=QQYBDL3OYZOZGIYNH6LMIAFL

2 Likes

Updated working version where internal list gets created and updated appropriately when deleting. See the clone link.

Have fun!

fun

https://anvil.works/build#clone:HG4GTRN3AJXJHVIG=DWSJPCA2IJDQYXBUPWIS5MKM

3 Likes

First of all - I love this!!! Thank you all!

Secondly, is there any way to make the drag switchable - ie so you can turn it on and off from code.

I tried reading the docs and re initing the muuri grid but it clears all the items that have been added.
The second thing I tried was reading this section of the Muuri docs but have no idea how to implement it.

Any help would be greatly appreciated.

1 Like

@rickhurlbatt, there is a bool parameter in the constructor for that “dragEnabled”

Ive added a parameter to the drag grid component from this Drag and Drop Trello Clone post.

You can just use the drag grid as a list and you should be much more flexible that way.
Anyway just check out the drag_enabled parameter on the custom component below and you should get hang of it :ok_hand:
https://anvil.works/build#clone:PI3PRHB66SBA6H7A=VEVTTNFBGRB27FBWHVLNXR3U

Cheers, Mark

2 Likes

Thanks very much @mark.breuss - I knew I had seen some details somewhere!

Much appreciated