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.

e.g.

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.

E.g.

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++;

  }

}
4
  • I love the examples you give here. I have finally gotten the sortable list to sort, but it doesn't appear to be posting... I can't figure out what's going on. Got any ideas? Commented Oct 9, 2014 at 5:42
  • You use $.ajax in your JS (like above) and post it to a route in your routes.php file e.g. Route::post('api-ch-order', 'SomeController@SomeFunction'); then use what I have above for the controller. That should work... Commented Oct 9, 2014 at 12:51
  • 1
    If still no luck after this then post up a new question and link it to me here and I'll see if I can help :) Commented Oct 9, 2014 at 12:55
  • Thank you. I'm pretty sure I have my route correct. If it were wrong then I should get an error from Laravel saying the route is wrong, correct? I get those errors often enough that I would know how to fix the problem if I saw the error. Anyway, here is the link to my post: stackoverflow.com/questions/26280943/… Commented Oct 9, 2014 at 14:33

2 Answers 2

3

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
Sign up to request clarification or add additional context in comments.

1 Comment

Perfect. That's exactly what I ended up going with! Will post full answer as an edit to my question.
0

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 :)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.