简体   繁体   中英

Saving serialised sortable data from jQuery/ajax using Laravel 4+

Having an issue working out the best way to save an ajax sortable list into my database. I'm using HTML5Sortable and Laravel 4.2 framework. The basic end result I'm trying to achieve is for a user to be able to click and drag the list items and reorder them and this new order will be saved in the database in a field called "order" so that when they return to the page later the new order will be present.

I have a list of chapters on the page like so:

<ul class="sortable">
    @foreach ($chapters as $chapter)
      <li class="ui-state-default" data-order="{{ $chapter->order }}">{{ $chapter->title }}</li>
    @endforeach
</ul>

And I can drag and drop sort these using HTML5Sortable and then serialize this data and submit it via ajax POST, which fires off each time the list is reordered like so:

$('.sortable').sortable().bind('sortupdate', function(e, ui) {

    var order = $('ul.sortable li').map(function(){ 
        return $(this).data("order");
    }).get();

    var uuid = "<?php echo$uuid; ?>";

    $.ajax({
        type: "POST",
        url: "api-ch-order",
        dataType: "json",
        data: {order: order, uuid: uuid},
        success: function(order){
          console.log(order)
        }
    });
});

My controller at /api-ch-order gets the data and saves the new order like so:

if(Request::ajax()){

  $uuid = Input::get('uuid');
  $order = Input::get('order');

  $i = 1;

  foreach($order as $position) {

    $chapter = Chapter::where('book_uuid', $uuid)->where('order', $position)->first();

    $chapter->order = $i;
    $chapter->save();

    $i++;

  }

}

THE PROBLEM

The issue I'm having with this approach is that it wont work in some circumstances, the loop causes problems.

eg

LOOP 1: FIND Chapter where order = 2 and change order to 1

LOOP 2: FIND Chapter where order = 1 and change it to 2

The problem here is that in LOOP 2 it is finding result of LOOP 1 and updating this instead... I think... This problem is confusing me quite a bit... But I'm 99% sure the foreach loop in my controller is the problem and I'm not sure the best approach to fix this.

Resources to link to this question:

THE ANSWER!!!

As r4xz mentioned, the answer is to use ID as the constant.

Eg

HTML

<ul class="sortable">
    @foreach ($chapters as $chapter)
      <li class="ui-state-default" data-id="{{ $chapter->id }}">{{ $chapter->title }}</li>
    @endforeach
</ul>

JS

$('.sortable').sortable().bind('sortupdate', function(e, ui) {

    var id = $('ul.sortable li').map(function(){ 
        return $(this).data("id");
    }).get();

    var uuid = "<?php echo$uuid; ?>";

    $.ajax({
        type: "POST",
        url: "api-ch-order",
        dataType: "json",
        data: {id: id, uuid: uuid},
        success: function(order){
          console.log(id)
        }
    });
});

PHP CONTROLLER

if(Request::ajax()){

  $uuid = Input::get('uuid');
  $id = Input::get('id');

  $i = 1;

  foreach($id as $val) {

    $chapter = Chapter::where('id', $val)->first();

    $chapter->order = $i;
    $chapter->save();

    $i++;

  }

}

The most common solution is to save position and entity id:

<li data-id="{{ $chapter->id }}" data-order="{{ $chapter->order }}">{{ $chapter->title }}</li>

Then in controller you simply use:

UPDATE chapter SET order = $order WHERE id = $id

This question was very helpfull and gives a selfanswer into it ! GREAT ! Thanks !

Just for those in my case not using the same structure. This is what I did :

public function myRouteFunction(Request $request)
    foreach($ids as $key => $id) {
        $update = DB::table('mybase')->where('id', $id)->update(['sort_order' => $key]);
    }
}

Maybe this could help someone :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM