0

I need help with saving a drag n drop menu order. I use http://farhadi.ir/projects/html5sortable to drag and update the list. Each menu item has two hidden fields: id and order. The order is updated dynamically when dropped. I don't know how to turn the fields id and order into a correct array so I can update via AJAX into Laravel.

HTML - Menu :

<div>
    <input name="menu[1][id]" type="hidden" value="1">
    <input name="menu[1][order]" class="new-order" type="hidden" value="3">
</div>
<div>
    <input name="menu[2][id]" type="hidden" value="2">
    <input name="menu[2][order]" class="new-order" type="hidden" value="4">
</div>
<div>
    <input name="menu[3][id]" type="hidden" value="3">
    <input name="menu[3][order]" class="new-order" type="hidden" value="5">
</div>

jQuery - Drag/drop, update order value then send via ajax :

// Sortable options
$('.nav-pages__items').sortable({
    handle: '.nav-pages__drag',
    items: ':not(.home)'
}).bind('sortupdate', function() {

    // When dropped clear list order
    $(this).find('input[name=menu]').attr('value', '');
    // Then update list order
    $('.nav-pages__items li:not(.home)').each(function(i, element) {
        element = i+1;
        $(this).find('input.new-order').attr('value'),
            $(this).find('input.new-order').attr('value', + element);
    });

    // !! Somehow create array to send/save !!

    // Ajax to send
    $.post('/menu-update', {
        _token: token,
        id: id,
        order: order
    }, function(data) {
        if (data.status == 'success') {
            console.log('success: ', data);
        } else if (data.error == 'error') {
            console.log('error: ', data);
        };
    });

});

PHP/Laravel - Not got this far (without errors):

public function update()
{
    $menu = Input::all();

    $save = Page::where('id', $menu['id'])->update([
        'order' => $menu['order']
    ]);

    if ($save) {
        $response = [
            'status' => 'success',
            'msg' => 'Message here',
            'id' => $menu['id'],
            'order' => $menu['order'],
        ];
    };

    return Response::json($response);
}

To summarise:

  1. Get the id and order for each field group
  2. Loop though them in js and crate correct array
  3. Send array to Laravel and update order based on id

Also, if there's a much simpler way to do this, I'm all ears.

8
  • Can you explain this line of code: $(this).find('input.new-order').attr('value'), $(this).find('input.new-order').attr('value', + element); It looks to me like that first find() isn't doing anything -- am I crazy? Commented Aug 6, 2015 at 17:51
  • I hadn't updated the field name. It's clearing the list order and starting it again (1, 2, 3, desc) Commented Aug 6, 2015 at 17:54
  • Can you tell me what $(this).find('input.new-order').attr('value') returns in your sortable function? I can't create the final order array without knowing that. Commented Aug 6, 2015 at 17:57
  • What is input.new-order ? Can you show the HTML for that element? Commented Aug 6, 2015 at 18:11
  • I'm not seeing the necessity of all of those hidden id and order elements -- I think this can be done using only the inputs that they're dragging and dropping, but I can't submit this an an answer without knowing more about those inputs. Commented Aug 6, 2015 at 18:13

1 Answer 1

3

I don't believe you need those hidden inputs -- what about something like:

jQuery:

// Sortable options
$('.nav-pages__items').sortable({
    handle: '.nav-pages__drag',
    items: ':not(.home)'
}).bind('sortupdate', function() {

    // Collect the new orderings
    var newOrders = [];
    $('.nav-pages__items li:not(.home)').each(function(i, element) {
        var id = $(element).data('id'); // Set a data-id attribute on each li
        var order = i;
        newOrders[order] = id;
    });

    // Ajax to send
    $.post('/menu-update', {
        _token: token,
        newOrders: newOrders
    }, function(data) {
        if (data.status == 'success') {
            console.log('success: ', data);
        } else if (data.error == 'error') {
            console.log('error: ', data);
        };
    });

});

PHP/Laravel:

public function update()
{
    $responses = [];
    foreach (Input::get('newOrders') AS $order => $id) {
        $save = Page::where('id', $id)->update([
            'order' => $order
        ]);

        if ($save) {
            $response[$id] = [
                'status' => 'success',
                'msg' => 'Message here',
                'id' => $id,
                'order' => $order,
            ];
        }

    }


    return Response::json($responses);
}
Sign up to request clarification or add additional context in comments.

6 Comments

Just heading home now - I'll check when I get back :)
The above gives me a Uncaught TypeError: Cannot set property '0' of undefined error on newOrders[order] = id; - However I've slightly adjusted it and posted the answer below. But as it's all based on the above I'm going to answer this as correct and post my version below :)
Sorry, I forgot to initialize the array. Should be fixed now.
Had to swap $id => $order to $order => $id` and it's worked perfectly :)
Thank you so much again for your help :)
|

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.