Vue implements user-defined list, drag list sorting and display

Vue implements user-defined list, drag list sorting and display

1, Question

  • On the list editing page, you can drag and edit the header information. The editing contents include: the order of sorting the list and whether each column of the list needs to be displayed
  • The master plan has two major requirements: drag the sorted list and display the corresponding list information according to the sorted header order

2, Settle

1. Solve user-defined list drag sorting

  • First, solve the problem of drag sorting. Because it is a Vue project, you can use the vuedraggable component in the component library to drag and sort the list

  • Download the vuedraggable component (the same applies to cnpm)

    npm install vuedraggable -S
    
  • Import and register on the page where the component needs to be used. The import and use method is similar to that of the user-defined component. Here is the headtitledit.vue interface:

    import draggable from 'vuedraggable'
    ...
    components: { draggable }
    
  • Nest the component into the outer layer of the list to be sorted by dragging, and bind the list data to be sorted by using the v-model instruction (here is an array); Similarly, the component supports binding a function using the syntax sugar @ update. Dragging the list to change the order will trigger the function and return the new index and the old index; The animation effect can be changed by binding the dynamic attribute: options="{animation:300}". The code of the template part of the list is as follows:

    <div class="edit-card-contian">
        <draggable
                   v-model="titleList"
                   @update="datadragEnd"
                   :options="{animation:300}"
                   >
            <div
                 class="edit-title-item"
                 v-for="item in titleList"
                 :key="item.id"
                 >
                <span :class="item.isCheck?'edit-title-select':''">{{item.name}}</span>
                <div>
                    <el-checkbox v-model="item.isCheck"></el-checkbox>
                    <i class="el-icon-s-unfold"></i>
                </div>
            </div>
        </draggable>
    </div>
    
  • Through the demonstration of local simulation data, take a brief look at the data structure of the user-defined list, where field_name is the key to sorting the column contents later

    data() {
        return {
            ...
            titleList: [{
                id: 1,
                name: 'full name',
                field_name: 'name',
                isCheck: true,
            }, {
                id: 2,
                name: 'Age',
                field_name: 'age',
                isCheck: true,
            }, {
                id: 3,
                name: 'Gender',
                field_name: 'sex',
                isCheck: true,
            }, {
                id: 4,
                name: 'occupation',
                field_name: 'position',
                isCheck: true,
            }, {
                id: 5,
                name: 'Salary Expectation ',
                field_name: 'pay',
                isCheck: true,
            }], // List item
        };
    }
    
  • The display effect of the page is as follows:

  • After dragging the list to change the position, the event bound by @ update will be triggered. Here, the list data will be printed. After viewing the list data after changing the position, you can see that the array order is consistent with the order after dragging:

  • Click OK or save to pass the data to the back end for saving, which is convenient for use in the subsequent custom list page. If the checkbox is not checked, just change the value of the current corresponding data isCheck, it will still be saved in the array. The problem of dragging and sorting here will be solved!

2. Solve the problem of displaying user-defined list data according to header data

  • The difficulty of this requirement is how to display the contents of the list according to the order of header data and use the fields in header data_ Name field, which is the key to display. The form data content is as follows, which is still simulated data:

    data() {
        return {
            ...
            bodyList: [
            {
              id: 1,
              name: 'Xiao Ming',
              age: 22,
              sex: 'male',
              position: 'Front end Engineer',
              pay: '11K'
            },
            {
              id: 2,
              name: 'Xiao Hong',
              age: 23,
              sex: 'male',
              position: 'product manager',
              pay: '15K'
            },
            {
              id: 3,
              name: 'Xiao Li',
              age: 22,
              sex: 'male',
              position: 'architect ',
              pay: '21K'
            },
            {
              id: 4,
              name: 'cockroach',
              age: 21,
              sex: 'male',
              position: 'Back end Engineer',
              pay: '18K'
            },
            {
              id: 5,
              name: 'Xiao Gang',
              age: 25,
              sex: 'male',
              position: 'Back end Engineer',
              pay: '16K'
            }
          ],
        }
    }
    
  • The header in the template is displayed by using the v-for loop, and the list content part needs to use the double v-for loop. The first layer traverses the list content data bodyList, and the second layer uses the template to wrap the cyclic header data titleList. The code is as follows:

    <!-- List section -->
    <div class="ca-contain">
        <!-- List header -->
        <div class="long-list list-title">
            <span
                  v-for="item in titleList"
                  :key="item.id"
                  >{{item.name}}</span>
            <span>operation</span>
        </div>
        <!-- List table body -->
        <div
             class="long-list list-body"
             v-for="item in bodyList"
             :key="item.id"
             >
            <template v-for="headItem in titleList">
                <span
                      :title="item[headItem.field_name]"
                      :key="headItem.field_name"
                      >{{item[headItem.field_name]}}</span>
            </template>
            <span class="operate">
                <i
                   class="iconfont icon-shanchu"
                   @click="delCur(item)"
                   ></i>
            </span>
        </div>
    </div>
    
  • In the style, a minimum width can be given to each div in the header and table body, and ellipsis will be displayed for the excess. The style is shown in the following figure and will not be repeated:

  • Here, the contents of the list are displayed in the order of header data in the user-defined list. The last thing to do is to judge whether the current field is selected (displayed), that is, whether isCheck is true. You can use Sanmu in the loop or filter through the filter according to your preferences. The code is as follows:

    this.titleList.filter(({ isCheck }) => { return isCheck == true })
    
  • The final effect is as follows:

The above has completed all the requirements of custom forms. If there are better methods, please supplement and discuss 🌈

Tags: html Javascript Vue.js Vue elementUI

Posted by Sarok on Wed, 22 Sep 2021 10:34:57 +0530