Search code examples
ajaxlaravelnested-setsjqtree

nested set save to database


I'm trying to implement jqTree with Laravel app.

  1. Controller gets data and return view:

    public function index()
    {
        $categories = Category::get(['id', 'name', '_lft', '_rgt', 'parent_id'])->toTree();
        return view('category.index', [
            'categories' => $categories
        ]);
    }
    
  2. Here is a view (javascript part):

    var data = {!! $categories !!};
    
    $('#tree').tree({
            data: data,
            dragAndDrop: true,
            onDragStop: handleMove,
    });
    
    function handleMove() {
        var treeData = $('#tree').tree('toJson');
    
    
    $.ajax({
        url: 'category',
        type: 'POST',
        headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') },
        data: { data: treeData },
    });
    
    }
  3. This builds tree properly and I can drag & drop items. However, I want to save reordered tree back to database. Here is a post method in a controller:

    public function store(Request $request)
    {
      $data = $request->data;
      $result = Category::rebuildTree($data);
      ...
    }
    

After calling rebuildTree method, I'm getting this error:

Type error: Argument 1 passed to Kalnoy\\Nestedset\\QueryBuilder::rebuildTree() must be of the type array, string given

I have tried with this:

public function store(Request $request)
{
  $data = $request->data;
  $data = json_decode($request->data);
  $array_data = (array) $data;
  $result = Category::rebuildTree($data);
  ...
}

This however returns:

Cannot use object of type stdClass as array

How can I get array of data passed so I can use rebuildTree() method and update database?

Here is a result of dd($request->data):

[{"name":"Storage","id":3,"_lft":17,"_rgt":18,"parent_id":null,"is_open":true,
    "children":[{"name":"Laptops","id":1,"_lft":1,"_rgt":10,"parent_id":null,"is_open":true,
    "children":[{"name":"Monitors","id":2,"_lft":11,"_rgt":16,"parent_id":null,
    "children":[{"name":"IPS","id":5,"_lft":14,"_rgt":15,"parent_id":2}]},
    {"name":"Macbook","id":6,"_lft":2,"_rgt":3,"parent_id":1},
    {"name":"Acer","id":7,"_lft":4,"_rgt":5,"parent_id":1},
    {"name":"New Subcategory Name","id":8,"_lft":6,"_rgt":7,"parent_id":1},
    {"name":"New Subcategory ame","id":9,"_lft":8,"_rgt":9,"parent_id":1}]}]},
    {"name":"Memory","id":4,"_lft":19,"_rgt":20,"parent_id":null}]

Also, just to be clear: I'm using jqTree

Nested set is lazychaser/laravel-nestedset


Solution

  • You are getting json in $request->data; you need to decode it in array using json_decode() along with second parameter as true for assoc

    see the manual

    assoc

    When TRUE, returned objects will be converted into associative arrays.

    public function store(Request $request)
    {
      $result = Category::rebuildTree(json_decode($request->data,True));
      ...
    }
    

    and if you need to pass it in $data then pass it like this.

    $data = json_decode($request->data,True);
    

    Alternatively

    foreach ($request->data as $value) 
        $array[] = $value->name;
    

    then pass this $array into your query like this

    $result = Category::rebuildTree($array);