Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

ahmadbadpey's avatar

makeNthChildOf() method is missing on etrepat/baum laravel package

I am using etrepat/baum laravel package along with jstree jQuery plugin to manage categories.

In jstree there is a move_node.jstree method used to move nodes. it has useful properties to get info about move action like parent , old _parent, ... and a position that returns new position of moved child node in parent node.

In the other hand there is methods to move nodes too.(here). but there is not any method like makeNthChildOf() that can use to place a child node at specific position of a parent node. like:

$node->makeNthChildOf(newPosition , $parent)

Now in the client to move nodes I wrote this:

 $treeview.on('move_node.jstree', function (e, data) {
            $.post('/move', {
                'CategoryID': data.node.id,
                'newParent': data.parent,
                'oldParent': data.old_parent
            }, function (res) {
                data.instance.open_node(data.parent);
            }, 'json');
        });

And in the laravel :

public function move (Request $request)
    {
        $data = $request->only('newParent', 'oldParent', 'CategoryID');

        $currentNode = Category::find($data['CategoryID']);
        if ($data['newParent'] == '#') {
            $currentNode->makeRoot();
        } else {
            $currentNode->makeChildOf($data['newParent']);
        }

        return ['success' => true];
    }

But above code can not do that I want and just can to move a node from a parent to another parent.

I want to know is there any alternate approach to doing that functionality ?

0 likes
2 replies
noimad1's avatar

did you ever find a solution to this?

noimad1's avatar

Ok, I believe I found a way to accomplish this. I just threw it together quickly, so sorry for the ugly code:

First, I use ajax, so I build up the form data with the node information

formData = "node_id=" + data.node.id + "&name=" + data.node.text + "&_token=" + $("input[name=_token]").val() + "&parent=" + data.parent + "&position=" + data.position + "&old_position=" + data.old_position + "&old_parent=" + data.old_parent;

Next, we create a quick helper function to determine what position our current node is in. It will just loop through all the decendants of the parent node and literally count them.

private function findPosition($decendants, $position) {
        $i = 0;
        foreach ($decendants as $decendant) {
            if ($i == $position) {
                return $decendant;
            }
            $i++;
        }
    }

And then we can move the node to it's correct spot:

 //We first need to account for moving within same node, but below it's current position.  Without this the node will be moved 1 position off.
        if ($parent == $old_parent) {
            if ($position > $old_position) {
                $position = $position +1;
            }
        }


        $parent = BaumTest::find($parent);
        $decendants = $parent->getImmediateDescendants();
        $moveTo = $this->findPosition($decendants, $position);
        $node = BaumTest::find($node_id);

    //If the parent we are moving to doesn't have any decendents,  just move it now
        if ($parent->isLeaf()) {
            $node->makeChildOf($parent);
            return array("error"=>false, "successMessage"=>"Sucessfully Moved!");
        }

       //This takes care of it we are moving it into the last position
        if (is_null($moveTo)) {
            $node->makeLastChildOf($parent);
            return array("error"=>false, "successMessage"=>"Sucessfully Moved!");
        }

     $node->moveToLeftOf($moveTo);

Please or to participate in this conversation.