-1

I'm trying to make a sortable table in my laravel app where the order also needs to be updated in the database, I'm trying to do it with jquery, ajax.

I tried to figure it out with this pieces of code:

JQuery/Ajax

$(document).ready(function () {
        $('table tbody').sortable({
            update: function (event, ui) {
                $(this).children().each(function (index) {
                    if ($(this).attr('data-position') != (index + 1)) {
                        $(this).attr('data-position', (index + 1)).addClass('updated');
                    }
                });

                saveNewPositions();
            }
        });
    });

    function saveNewPositions() {
        var positions = [];
        $('updated').each(function () {
            position.push([$(this).attr('data-index'), $(this).attr('data-position')]);
            $(this).removeClass('updated');
        });

        $.ajaxSetup({
            headers: {
                'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
            }
        });

        $.ajax({
            url: 'cursos',
            method: 'POST',
            dataType: 'text',
            data: {
                'updated': 1,
                'positions': positions,
                '_token': '{{ csrf_token() }}'
            },
        })

Then in my web.php I created a post route:

Route::post('/cursos', function (Request $request){
return SectionCourseController::updateOrder($request);})->name('post');

In my controller I created this function:

        public static function updateOrder(Request $request)
{
    var_dump($request->positions);
    foreach ($request->positions as $position) {
        $index = $position[0];
        $newPosition = $position[1];
        $seccion = SectionCourse::findOrFail($index);
        $seccion->order = $newPosition;
        $seccion->save();
    }

    return response('success', 200);
}

When I'm trying to update the order, I'm having an error on the console of 500 (Internal Server Error).

[2022-06-14 14:16:18] local.ERROR: foreach() argument must be of type array|object, null given {"userId":1,"exception":"[object] (ErrorException(code: 0): foreach() argument must be of type array|object, null given

Sorry if I'm doing something bad on Ajax, this is the first time I try to do something on it.

  • 1
    A 500 error is a very generic error that covers almost all of the PHP errors. Check your server error logs as well as your Laravel logs in `storage/logs`, which should give you more information. I wonder if it's throwing the error at `findOrFail` if it can't find the model. – aynber Jun 14 '22 at 13:39
  • Thanks @anyber I didn't know that you could check the logs of each error. – Francisco Flores Jun 14 '22 at 13:57
  • 1
    Laravel has it's on request functions, so you don't need to use `$_POST`. Instead, try `request()->get('positions')` or inject the request into the function with `updateOrder(Request $request)` and use `$request->get('positions')` – aynber Jun 14 '22 at 14:00
  • When you set `dataType: 'text',` and then add a javascript object as an attribute `positions: positions,` how do you expect it to convert it? `$request->get('positions')` will return the text `[object Object]` which is the JS conversion of an object to text. Use json dataType or stringify the object and then json decode it in your controller. – N69S Jun 14 '22 at 14:40

3 Answers3

-1

I've done something very similar to this, so as I see it right now you are firstly missing a csrf token, so in the view add this below the code where you declare the $('updated') each.

$.ajaxSetup({
    headers: {
        'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
    }
});

$.ajax({
    method: 'POST',
    dataType: 'json',
    url: 'cursos', // No {{}} needed here
    data: {
        update: 1,
        orders: orders,
         _token: '{{ csrf_token() }}'
     },
});

Next your controller is a mess. So rewrite it to fit at least some of laravels writing standards. Something like this

public function updateOrder(Request $request)
{
    foreach ($request->positions as $position) {
        $index = $position[0];
        $newPosition = $position[1];
        $seccion = SectionCourse::findOrFail($index);
        $seccion->order = $newPosition;
        $seccion->save();
    }

    return response('success', 200);
}

Also add the following when declaring .sortable

axis: 'y',
containment: 'parent',
update: ...
dz0nika
  • 882
  • 1
  • 5
  • 16
-1

Add a meta-tag to each page, or master layout

     <meta name="csrf-token" content="{{ csrf_token() }}"> and add to your js page

 $.ajaxSetup({
  headers: {
    'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
  }

});

Dont forget to add data inside

$.ajax({
url: "test",
type:"POST",
data: { '_token': token, 'someOtherData': someOtherData },
Shkelqim
  • 7
  • 4
-2

There is 2 cases for 500 internal server error

  1. you had not put the {csrf} token there when sending request through ajax.
  2. Use new FormData() object while sending response through ajax and use these params with processData: false,contentType: false,type: 'POST'