Как сделать сортируемое селектирование умноженным в рюкзаке Laravel? - PullRequest
0 голосов
/ 02 июля 2018

Мне нужно сделать сортируемое select2_multiple с Laravel Backpack - или пользовательский с аналогичной функциональностью.

В документации есть способ просто реализовать select2_multiple следующим образом:

$this->crud->addField([
    'label' => "Ingredients",
    'type' => 'select2_multiple',
    'name' => 'ingredients', // the method that defines the relationship in your Model
    'entity' => 'ingredients', // the method that defines the relationship in your Model
    'attribute' => 'name', // foreign key attribute that is shown to user
    'model' => Ingredient::class, // foreign key model
    'pivot' => true,
    'select_all' => true    
]);

Но! Я не вижу способа хранить сортировку данных записей, которые мы выбрали!

Я создал поле SORT в моей базе данных ингридиенты_в_продуктах таблица, это должно сработать, но как реализовать это в рюкзаке?

Структура БД действительно проста: таблицы products, ингридиенты, ингридиенты_продукты. Ingredients_to_products В таблице есть только 3 поля: product_id , ингридиент_id , sort .

Laravel 5.6, Рюкзак CRUD 3.3

Любая помощь приветствуется. Спасибо!

1 Ответ

0 голосов
/ 12 июля 2018

Я нашел, как это сделать.

Я сделал собственное представление и внес некоторые изменения в CrudController, вручную разрешив значение сортировки. В разделе просмотра я создал несколько JS и новые поля, которые представляют значения сортировки соответствующих записей. Кстати, есть функция $ entry-> pivot , которая также может помочь.

Итак, что я сделал: создал новый вид под названием «ингредиенты»

<table class="table table-bordered" id="table">
    <p>Connected ingredients:</p>
<select hidden multiple name="ingredients[]" id="ingredients">
        <?php foreach ($field['value'] as $item){ ?>
            <option selected data-id="<?= $item->id  ?>"  value="<?= $item->id  ?>"><?= $item->name  ?></option>
        <?php } ?>
    </select>

<select hidden multiple name="ingredients_sort[]" id="ingredients_sort">
    <?php foreach ($field['value'] as $item){ ?>
        <option data-id="<?= $item->id ?>" selected  value="<?= $item->pivot->sort  ?>"><?= $item->pivot->sort  ?></option>
    <?php } ?>
</select>

    <?php foreach ($field['value'] as $item){ ?>
        <tr class="item">
            <td>
                <p><?= $item->name  ?></p>
            </td>
            <td>
                <input class="sorter form-control" data-id="<?= $item->id ?>" value="<?= $item->pivot->sort  ?>">
            </td>
            <td>
                <span data-id="<?= $item->id  ?>" class="btn btn-primary remover">Remove</span>
            </td>
        </tr>
    <?php } ?>

Итак, как вы видите, теперь у нас есть ингредиенты и ингридиенты_сорта массивы, которые синхронизируются по позициям с помощью JavaScript.

Мы получаем список всех доступных ингредиентов от AJAX. Значение сортировки - это связанное поле ввода для каждой записи ингредиента.

let selected_ingredients = <?= isset($field['value']) ? json_encode($field['value']) : '' ?>;
let ingredients = [];

document.addEventListener("DOMContentLoaded", load);

function load(){
    getIngredients();
}

function getIngredients() {
    $.get('/ingredients/get').done( (response) => {
        ingredients = JSON.parse(response);
        printList(ingredients);
    } );
}

function printList(ingredients){

    // @todo : print search

    for (let i = 0; i < ingredients.length; i++){
        let item = ingredients[i];
        let _item = document.createElement('div');
            _item.className = 'item btn btn-default';
            _item.setAttribute('data-id', item.id);
            _item.innerHTML = `${item.name}`;
            _item.onclick = function () {
                // @todo: add ingredient to product

                let needAdd = true;

                for (let i = 0; i < selected_ingredients.length; i++){
                    if (selected_ingredients[i].id == item.id){
                        needAdd = false;
                    }
                }

                if (needAdd){

                    $('#ingredients').append(`<option selected data-id="${item.id}" value="${item.id}">${item.name}</option>`);
                    $('#ingredients_sort').append(`<option data-id=${item.id} selected value="0">0</option>`);

                    $('#table').append(
                        `<tr><td>
                            <p>${item.name}</p>

                            </td>
                            <td>
                                <input class="sorter form-control" data-id="${item.id}" value="0">
                            </td>
                            <td>
                                <span data-id="${item.id}" class="remover btn btn-primary">remove</span>
                            </td>
                         </tr>`);

                    $('.remover').unbind().click(function () {
                        $(this).parent().parent().remove();
                    });

                    $('.sorter').unbind().change(function(){
                        let id = $(this).attr('data-id');
                        $(`#ingredients_sort [data-id=${id}]`).val( $(this).val() ).html( $(this).val() );
                    });
                }

            };


        $('#list').append(_item);
    }

    $('.remover').unbind().click(function () {
        let id = $(this).attr('data-id');
        $(`#ingredients [data-id=${id}], #ingredients_sort [data-id=${id}]`).remove();
        $(this).parent().parent().remove();
    });

    $('.sorter').unbind().change(function() {
        let id = $(this).attr('data-id');
        $(`#ingredients_sort [data-id=${id}]`).val( $(this).val() ).html( $(this).val() );
    });
}


function remove(){
    console.log(this);
}

И последний шаг - помещение метода Update в ItemCrudController (который в моем приложении является контроллером "product")

public function update(UpdateRequest $request)
{
     // your additional operations before save here
    $redirect_location = parent::updateCrud($request);

    $obj = \App\Models\Item::find( $request->get('id') );

    $obj->ingredients()->detach();

    $i = 0;
    foreach ( $request->get('ingredients') as $item){
        $obj->ingredients()->save( \App\Models\Ingredient::find($item), ['sort' => $request->get('ingredients_sort')[$i]]);
        $i++;
    }

    return $redirect_location;
}

Итак - это работает . Результат фото ниже. Надеюсь, это кому-нибудь поможет.

enter image description here

...