Saving Nested Sortables with PHP

See original GitHub issue

Hi all,

I have very limited knowledge of JS (but decent knowledge of PHP). So I’m trying to properly pass to PHP the order of my nested items.

Problem:

What I have is a list of nested items, each with a hidden input field. So when I POST the form, I use the names and values of those fields in the order that they appear in the DOM.

<input type="hidden" class="menu-item-checkbox" name="menu-items[]" value="2"> <input type="hidden" class="menu-item-checkbox" name="menu-items[]" value="3"> <input type="hidden" class="menu-item-checkbox" name="menu-items[]" value="4">

In PHP I get these values into an array and then can do what I want with it. It all works great when there’s only one level of parent items. But the nested items make no difference.

This is the current JS code that I have to make nested sortables:

<script>
                   // Nested demo
                    var nestedSortables = [].slice.call(document.querySelectorAll('.nested-sortable'));

                    // Loop through each nested sortable element
                    for (var i = 0; i < nestedSortables.length; i++) {
                        
                        new Sortable(nestedSortables[i], {
                            ghostClass: 'ghost-placeholder',
                            handle: '.handle',
                            group: 'nested',
                            dataIdAttr: 'data-id',
                            animation: 120,
                            fallbackOnBody: true,
                            invertSwap: true,
                            swapThreshold: 0.60,
                            emptyInsertThreshold: 30,
                        });


                    }
</script>

Due to my limited knowledge of JS, I have no idea how to pass the order of my nested sortables in any way as a POST field in my main form, or maybe as a separate AJAX request to a separate PHP file.

I have searched the documentation and existing/closed issues and I can’t seem to find any sample PHP code that would accomplish what I need.

I would prefer to save the order only once when the form is submitted, without having to keep a separate PHP file to handle separate AJAX requests.

Thank you all in advance for ANY guidance.

JSBin/JSFiddle demonstrating the problem:

What my HTML looks like: https://jsfiddle.net/s7dh2mko/

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:8 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
owen-m1commented, Jul 9, 2019

@dumitrub So why would that solution not work? It does exactly what you are asking. All you need to do is use this code:

const nestedQuery = '.nested-sortable';
const identifier = 'sortableId';
const root = document.getElementById('nestedDemo');
function serialize(sortable) {
  var serialized = [];
  var children = [].slice.call(sortable.children);
  for (var i in children) {
    var nested = children[i].querySelector(nestedQuery);
    serialized.push({
      id: children[i].dataset[identifier],
      children: nested ? serialize(nested) : []
    });
  }
  return serialized
}

Replace the identifier with the attribute on the HTML Element used to identify the item. For you it seems to be an id of some sort. You will have to put the ID on the element as data-id="id" in this case, and set the idenfitier variable in that code to 'id'. You say you want the children of the element to be an array accessible via the children property of a serialized item, which is exactly what that code already does. The nestedQuery should be a CSS selector for the nested list (ie. the nested Sortable list container that is inside the item), Lastly, the root variable should be set to the main Sortable container of the main list. Then you can call serialize and it will return the array.

Perhaps PHP has an issue converting this serialized list to a PHP array? In that case, please share the corresponding PHP code.

0reactions
dogukanakkayacommented, Nov 23, 2020

If you use ‘parent_id’ logic for it there is an easy way. You can build parent_id’s like that, if you set an data-parent-id to all sortable groups

window.nestedSortableSerialize = (sortable, sortableGroup) => {
    const serialized = [];
    const children = [].slice.call(sortable.children);
    for (let i in children) {
        const nested = children[i].querySelector(sortableGroup)

        // Find the closest sortable group and get it's data-parent-id attribute
        const parentId = children[i].closest(sortableGroup).getAttribute('data-parent-id')
        serialized.push({
            item_id: children[i].dataset['sortableId'],
            parent_id: parentId
        });
        if (nested){
            serialized.push(...nestedSortableSerialize(nested, sortableGroup))
        }
    }
    return serialized
}
Array
(
    [0] => Array
        (
            [id] => 1
            [parent_id] => 0
        )

    [1] => Array
        (
            [id] => 2
            [parent_id] => 0
        )

    [2] => Array
        (
            [id] => 3
            [parent_id] => 2
        )

    [3] => Array
         (
            [id] => 4
            [parent_id] => 2
        )
)

You can have an output like this.

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to Save Serialized Nested Sortable Data to MySQL Table ...
I fixed this issue with this update: table schema still is the same. modification for the jQuery script: var menuarray; $('ol.sortable').
Read more >
Nested Pages – Extensió del WordPress
Expandable tree view of your page structure · Enhanced quick edit offers configurable fields and additional options · Sortable page nesting updates in...
Read more >
Transactions - Propel, The Blazing Fast Open-Source PHP 5.5 ...
The transactions inside each save() will become nested, and therefore not translated into actual database transactions. Only the outmost transaction will become ...
Read more >
https://healthchoicegenerations.com/wp-content/plu...
Post sorting and nesting is saved in the background after changes are made to the structure. ... Sortable page nesting updates in real...
Read more >
Eloquent: Getting Started - Laravel - The PHP Framework For ...
In addition, these options may be combined to create multiple classes at once: # Generate a model and a FlightFactory class... php artisan ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found