【问题标题】:Laravel, VueJS - keeping 2 arrays in sync while dragging & droppingLaravel,Vue JS - 在拖放时保持 2 个数组同步
【发布时间】:2021-05-19 14:13:13
【问题描述】:

我目前有代码引用 vuejs 包来处理拖放,它正在工作。

包:

  • src="//cdn.jsdelivr.net/npm/sortablejs@1.8.4/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"

我有一系列复选框项,它们都绑定到一个名为“choices”的 v-model。

模板代码片段:

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

复选框值当前是人类可读的英语(尽管当前使用本地化)单词,选中后会显示在列表中,然后可以拖放以进行手动排序。随着复选框被选中和/或列表被排序,标记为“事件文本”的红色文本(屏幕截图)会更新。

我想保留该功能(使用人类可读的项目以便显示它们),但我还希望在一个数组中拥有一组对应的值,这些值包含单个单词名称(也称为变量名称),以便于使用在我的应用程序的另一个区域中进行引用、本地化处理和其他处理。

因此,我希望两个数组根据用户对正在拖放的数组所采取的操作保持同步。

我希望我想要实现的目标是有意义的。另一种方法——解析当前的英语单词——是可能的,但一旦引入本地化就会中断,因为那样显示的单词就不是英语了。

提前致谢。

【问题讨论】:

    标签: arrays laravel vue.js synchronization draggable


    【解决方案1】:

    我在 17 天内一直保持开放状态,并且一直在解决这个问题。我正在发布我提出的解决方案,以帮助将来可能遇到此问题的任何其他人和/或提示任何可能更有效的更好想法的人。

    我重构了代码以管理此模板代码 sn-p 中复选框的显示:

                <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 包自动管理以进行排序,当它通过拖放 UI 更新时,排序顺序等得到维护(如预期的那样)。

    因为我需要使用与显示名称关联的相应变量名称来复制它,所以我设置了 checkbox_list 对象来存储名称/值对,并添加了选中状态、排序顺序和 instr(仅在显示器的初始设置)

    我有一个关于选项的监视设置,以便它更新标题(用于显示)和 checkbox_list 数组。然后我操作该数组的副本以得到一个变量名数组,该数组根据选择中的相应显示值进行排序。

    如果有更有效的方法来做到这一点,我很想听听。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-09-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-27
      • 2017-12-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多