Laravel, VueJS - синхронизация 2 массивов при перетаскивании

В настоящее время у меня есть код, ссылающийся на пакеты vuejs для обработки перетаскивания, и он РАБОТАЕТ.

Пакеты:

  • src=//cdn.jsdelivr.net/npm/[email protected]/Sortable.min.js
  • src=//cdnjs.cloudflare.com/ajax/libs/Vue.Draggable/2.19.2/vuedraggable.umd.min.js
  • src=//unpkg.com/axios/dist/axios.min.js

У меня есть ряд флажков, привязанных к одной v-модели с именем выбора.

Фрагмент кода шаблона:

        <div class="form-group">  // One of the labels for the checkboxes...
            <div class="col-sm-2" style="text-align: center">
                <label class="control-label">@lang('messages.fields.category')</label>
                @include('v1.parts.tooltip', ['title' => trans('messages.admin.api.api_info_cat')])
            </div>

            // Other labels for checkboxes not shown
        </div>
        <div class="form-group">  // One of the checkboxes... others not shown
            <div class="col-sm-2">
                <input type="checkbox" class="form-control input-sm" v-model="choices"
                       id="{{ trans('messages.fields.category') }}"
                       value="{{ trans('messages.fields.category') }}"
                       name="category">
            </div>
            // Other  checkboxes not shown

    <div class="col-sm-4">
        <p>
            @lang('messages.admin.api.api_instr2')
        </p>

       // This is the portion to the right of screenshot, populated as boxes are checked

        <draggable tag="ul" v-model="choices" @start="drag=true" @end="drag=false" handle=".handle">
            <div class="list-group-item" v-for="choice in choices">
                @{{ choice }} <i class="handle fas fa-arrows-alt pull-right"></i>
            </div>
        </draggable>

    </div>

скриншот с флажками и сортируемым списком

Значения флажков в настоящее время представляют собой удобочитаемые английские слова (хотя в настоящее время используется локализация), которые, если они отмечены, отображаются в списке, который затем можно перетаскивать для ручной сортировки. По мере установки флажков и/или сортировки списка красный текст (скриншот) с пометкой «Текст события» обновляется.

Я хочу сохранить эту функциональность (используя удобочитаемые элементы, чтобы они отображались), но я также хочу иметь набор соответствующих значений в массиве, который содержит однословные имена (также известные как имена переменных) для упрощения ссылки, ручки для локализации и другой обработки в другой области моего приложения.

Итак, я хочу, чтобы два массива оставались синхронизированными на основе действий, которые пользователь выполняет с массивом, который перетаскивается.

Я надеюсь, что то, чего я пытаюсь достичь, имеет смысл. Альтернатива — синтаксический анализ текущих английских слов — возможна, но сломается, как только будет введена локализация, потому что тогда отображаемые слова не будут английскими.

Заранее спасибо.


person Phil    schedule 16.02.2021    source источник


Ответы (1)


Я держал это открытым для 17d и работал над проблемой. Я публикую решение, которое я придумал, чтобы помочь всем, кто может столкнуться с этим в будущем, И/ИЛИ подсказать всем, у кого есть лучшие идеи, которые могут быть более эффективными.

Я реорганизовал код для управления отображением флажков в этом фрагменте кода шаблона:

            <div class="form-group">
                <div v-for="item in checkbox_list" class="col-sm-2" style="text-align: center">
                    <label class="control-label">@{{ item.value }}</label>
                    <a v-if="item.instr" data-toggle="tooltip" :title="item.instr" data-placement="top">
                        <i class="fas fa-info-square purple"></i>
                    </a>
                </div>
            </div>
            <div class="form-group">
                <div v-for="item in checkbox_list" class="col-sm-2">
                    <input type="checkbox" class="form-control input-sm" v-model="choices"
                           :id="item.id"
                           :value="item.value"
                           :name="item.id">
                </div>
            </div>

Мой код Vue выглядит следующим образом:

    new Vue({
        el: '#el',
        data: {
            admin_props: @json($admin_props),
            separator: '{{ $org_props[0]->value }}',
            header: '{{ $org_props[1]->value }}',
            choices: [],
            drag: false,
            checkbox_list: [
                {sort: 0, checked: 0, value: "@lang('messages.fields.category')", id: "category", instr: '@lang('messages.admin.api.api_info_cat')'},
                {sort: 0, checked: 0, value: "{!! trans_choice('messages.headers.et', 1) !!}", id: "et", instr: '@lang('messages.admin.api.api_info_et')'},
                {sort: 0, checked: 0, value: "@lang('messages.admin.api.api_times')", id: "api_times"},
                {sort: 0, checked: 0, value: "@lang('messages.headers.pdu_detail')", id: "pdu_detail"},
                {sort: 0, checked: 0, value: "@lang('messages.fields.memprice')", id: "memprice"},
                {sort: 0, checked: 0, value: "@lang('messages.fields.nonprice')", id: "nonprice"},
            ],
        },

        mounted: function () {
            this.choices = this.admin_props[1].value.split(' ' + this.separator + ' ',);
            this.varArray_update();
        },

        watch: {
            choices: function () {
                this.admin_props[1].value = this.choices.join(' ' + this.separator + ' ');
                this.api_update('header', this.admin_props[1].value);
                this.varArray_update();
            }
        },
        methods: {
            api_update: function (name, value) {

                axios.post('/panel/update', {
                    name: name,
                    value: value,
                })
                    .catch(error => console.log(error.response));
            },

            varArray_update: function() {
                var index = 0;
                this.checkbox_list.forEach(e => {
                    e.checked = 0;
                    e.sort = 0;
                });

                this.choices.forEach(element => {
                    index += 1;
                    console.log(index, element);
                    var x = this.checkbox_list.filter(function(ele) {
                        if(ele.value == element) {
                            ele.checked = 1;
                            ele.sort = index;
                        }
                    });
                });
                var out = [];
                var array_copy = this.checkbox_list;
                array_copy = array_copy.filter(function(v){ return v.checked == 1; });
                array_copy.sort((a, b) => (a.sort > b.sort) ? 1 : -1);
                array_copy.forEach(function(v) { out.push(v.id); });
                var id_hdr = out.join(this.separator);
                this.api_update('var_array', id_hdr);
            },
        }
    });

Массив вариантов автоматически управляется пакетом Vue для сортировки, и когда он обновляется с помощью пользовательского интерфейса перетаскивания, порядок сортировки и т. д. сохраняется (как и ожидалось).

Поскольку мне нужно было воспроизвести это с соответствующими именами переменных, связанными с отображаемыми именами, я настроил объект checkbox_list для хранения пар имя/значение и добавил проверенное состояние, порядок сортировки и инструкцию (текст инструкции, используемый только во время первоначальной настройки дисплей)

У меня есть настройка просмотра для выбора, так что он обновляет как заголовок (используемый для отображения), так и массив checkbox_list. Затем я манипулирую копией этого массива, чтобы перейти к массиву имен переменных, отсортированных в соответствии с соответствующими отображаемыми значениями в вариантах выбора.

Если есть более эффективный способ сделать это, я хотел бы услышать об этом.

person Phil    schedule 06.03.2021