Skip to content

[6.x] Ability to drag and drop between replicators#13042

Open
jacksleight wants to merge 6 commits intostatamic:6.xfrom
jacksleight:feature/replicator-group-dnd
Open

[6.x] Ability to drag and drop between replicators#13042
jacksleight wants to merge 6 commits intostatamic:6.xfrom
jacksleight:feature/replicator-group-dnd

Conversation

@jacksleight
Copy link
Contributor

@jacksleight jacksleight commented Nov 13, 2025

Update of #10361 for v6.

This PR adds the ability to drag and drop sets between different replicators:

CleanShot.2025-11-13.at.16.58.01-converted.mp4

Issues

There are a couple of issues with this in v6 that I've not yet figured out (help appreciated):

  • Set preview data seems to work differently in v6, the previews prop and updateSetPreviews methods no longer exist, so I've had to remove those calls. This means that previews get out of sync (wrong index) when you move a set from one replicator to another.
  • There are some UI spacing/margin inconsistencies between sets after they've been moved.

Additionally, the previous version relied on the closestVm function to track linked Vue components and allow replicators to talk to each other. This function no longer works in Vue 3 and I couldn't figure out how to make it work, so instead I changed the approach to have the sortable list component keep track of the related Vue components (lists var and owner prop). This doesn't feel like a very elegant solution (neither did closestVm), but I'm not sure how else to do it given the limitations of Shopfiy sortable.

Notes

  • I had to change the way the draggable instances are initialised so that the same instance can be shared between multiple lists, but this shouldn't impact any non-replicator lists.
  • The sortable list component accepts a new group prop that tells it which instance to share, and a groupValidator function that's used to decide whether the item is valid in the target container.
  • Replicators use a list of set config hashes to decide whether the set being dragged is compatible with the target replicator.
  • I had to give the set container a minimum height so that there was still a drop area available when the replicator is empty. This may need some adjustment.
  • If group is set the input event emitted from the sortable list component has different data, allowing the parent component to decide how to handle the changes.
  • The sortable list move helper function has been moved to globals and renamed/split up so that functionality can be used elsewhere.
  • Annoyingly there’s a bug in Shopify draggable that causes an uncaught error when dragging a set into an empty replicator. It doesn’t break anything, but it shows up in console. A fix was submitted but it doesn’t look like anything is happening with it unfortunately.

Other Changes

I’ve made a couple of changes that are not strictly drag-and-drop related, but were required to implement this nicely:

  • The hashes and blink keys have been slightly refactored. This PR requires hashes for each set type, and that PR needs the same thing. Rather than generating those twice both features now use the same list of set hashes.
  • I’ve also tweaked some of the other hashing to avoid having to hash the same config multiple times (which adds unnecessary overhead). Each field instance now only hashes its config once, which is implemented via a new configHash() method on the Field class (only called when needed).
  • I’ve updated a test that was creating a Bard object without setting a field. This meant that the field could be null when generating the config hash, resulting in blink keys that are pretty meaningless. Rather than allowing null I thought it made more sense to adjust the test.

@godismyjudge95
Copy link
Contributor

Glad you are resubmitting this; I was really looking forward to it being merged in 5.x :)

Set preview data seems to work differently in v6, the previews prop and updateSetPreviews methods no longer exist, so I've had to remove those calls. This means that previews get out of sync (wrong index) when you move a set from one replicator to another.

I bet the you could use the same approach as what I did for the errors: #11992
Specifically:
https://github.com/statamic/cms/blob/master/resources/js/components/ui/Publish/Field.vue#L73-L78
https://github.com/statamic/cms/blob/master/resources/js/components/fieldtypes/replicator/Replicator.vue#L299-L318

I mapped all the errors on first load to their set id so that they'd follow the set around. I think you could do the same for the previews.

@daun
Copy link
Contributor

daun commented Nov 19, 2025

Amazing 🥬 Thanks for working on this.

One thing I've been wondering is whether this should be opt-in to avoid surprises, with e.g. a group config to control the fields between which shared sets will work. That would allow explicitly linking instances. Imagining a scenario where there's two identical text set types between otherwise completely unrelated replicators. As an editor, I would find it confusing that I can move exactly one type of set and none of the others. Explicit linking/grouping would avoid that.

@jacksleight
Copy link
Contributor Author

jacksleight commented Nov 19, 2025

One thing I've been wondering is whether this should be opt-in to avoid surprises, with e.g. a group config to control the fields between which shared sets will work. That would allow explicitly linking instances. Imaging a scenario where there's two identical text set types between otherwise completely unrelated replicators. As an editor, I would find it confusing that I can move exactly one type of set and none of the others. Explicit linking/grouping would avoid that.

That's not a bad shout. Right now you can enforce that with careful set handle naming, but if you have different replicators with identical "item" sets for example things could get mixed up. Happy to look at options, whether it's just making this opt-in per replicator or something more granular like specific group names. Will see what the core team think.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants