I have a single HTML list which may contain zero or more nested lists. A nested list is never be more than one level down ie nested lists cannot contain itself nest a list. Users can add/remove nested lists.
When the page loads I loop through the top level of the root list with this:
const sortoptions = {
group: {
name: 'items',
pull: function (to, from, dragEl) {
return !dragEl.matches('[data-nested^="nested-"]') || !to.el.matches('[data-nested^="nested-"] > ol');
}
},
ghostClass: 'ghost',
store: {
get: function (sortable) {
let order = localStorage.getItem(sortable.options.group.name);
return order ? order.split('|') : [];
},
set: function (sortable) {
let order = sortable.toArray(),
n = order.join('|'),
o = localStorage.getItem(sortable.options.group.name);
if (n != o) { // changed
localStorage.setItem(sortable.options.group.name, order.join('|'));
}
}
},
animation: 150,
fallbackOnBody: true,
swapThreshold: 0.65
};
Sortable.create(document.querySelector('#root'), sortoptions);
And through nested lists with code like this:
let num = 1;
Sortable.create(document.querySelector('[data-nested="nested-' + num + '"]'), sortoptions);
The resulting list behaves as expected (for which I'm quite pleased):
- root items can be reordered
- items from a nested list can be moved to root or to another nested list
- nested lists can be reordered
- root items can be moved into nested lists
The issue I'm trying to resolve is how to add an undo capability to a list that contains nested lists.
Each time I try something the list is sortable but undo never seems to work.
Each call to Sortable.create creates a new instance and so I've no real idea how to know which items (parent and children) to store to localStorage that I'll later need for undo.
Do I just create an array of root and then and concatenate every nested list to it? But then how would I know if a nested lists new position?
I've made some progress. Before each call to "create" I add a "name" attribute
sortoptions.name = 'foo";
Sortable.create(document.querySelector(...
then in store I can refer to the specific Sortable using "name" eg:
store: {
get: function (sortable) {
const inst = sortable.options.group.name + '-' + sortable?.options?.name;
Also, for some unknown reason I needed to manually add a data attribute to each draggable item. If I left it up to Sortable the attribute values changed each time I dragged an item to a new location. My next step is dealing with sub-lists.