如何使用vue仅对表中显示的项进行排序

时间:2016-12-30 07:17:10

标签: filter dataset html-table vue.js

关于以下代码我有两个问题。

第一个问题:说我在数组中有四个项目,其中包含[1,2,4,5,7]的ID 如果我点击排序并且每页选择了2个项目,那么当我切换相反的顺序时,它会显示id为1& 2或5& 7的条目。 那么如何让表格只对分页视图中显示的项目进行排序?

第二个问题: 我们正在使用我们购买的管理模板中的vue和一些jquery的混合,但是在代码中写有<div class="checkbox checkbox-styled">的地方,除非我将Vue代码放在setTimeout中,间隔值为'100'或更多。 如果依赖于jquery的项目处于循环的vue中,它通常只会在jquery中很好地呈现内容。 有没有人对此有解释?

请注意我已经删除了尽可能多的问题以保持问题尽可能小。

<div class="section-body">
    <!-- BEGIN DATA TABLE START -->
    <form class="form" role="form">
        <div class="row">
            <div class="col-lg-12">
                <div id="" class="dataTables_wrapper no-footer">
                    <div class="table-responsive">
                        <table style="width: 100%" cellpadding="3">
                            <tr>
                                <td>
                                    <div class="dataTables_length" id="entries_per_page">
                                        <label>
                                            <select name="entries_per_page" aria-controls="datatable" v-model="itemsPerPage">
                                                <option value='2'>2</option>
                                                <option value='20'>20</option>
                                                <option value='30'>30</option>
                                            </select>
                                            entries per page
                                        </label>
                                    </div>
                                </td>
                            </tr>
                        </table>

                        <table class="table table-striped table-hover dataTable">
                            <thead>
                                <tr>
                                    <th>
                                        <div class="checkbox checkbox-styled">
                                            <label>
                                                <input type="checkbox" v-model="selectAll" :checked="allSelected" @click="selectAllCheckboxes">
                                            </label>
                                        </div>
                                    </th>
                                    <th v-bind:class="{'sorting': col.key !== sortKey, 'sorting_desc': col.key == sortKey && !isReversed, 'sorting_asc': col.key == sortKey && isReversed}" v-for="col in columns" @click.prevent="sort(col.key)">
                                        <a href="#" v-cloak>${ col.label | capitalize}</a>
                                    </th>
                                    <th class="text-right">Actions</th>
                                </tr>
                            </thead>
                            <tbody>
                                <tr v-for="item in items | paginate | filterBy search">
                                    <td width="57">
                                        <div class="checkbox checkbox-styled">
                                            <label>
                                                <input type="checkbox" value="${ item.id }" v-model="cbIds" :checked="cbIds.indexOf(item.id) >= 0" />
                                            </label>
                                        </div>
                                    </td>

                                    <!-- !ENTITY_NAME TABLE COLUMNS START -->
                                        <td v-cloak>${ item.id }</td>
                                        <td v-cloak>${ item.title }</td>
                                    <!-- !ENTITY_NAME TABLE COLUMNS END -->

                                    <td class="text-right">
                                        <button type="button" class="btn btn-icon-toggle" data-toggle="tooltip" data-placement="top" data-original-title="Edit row" @click="editItem(item)">
                                            <i class="fa fa-pencil"></i></button>
                                        <button type="button" class="btn btn-icon-toggle" data-toggle="tooltip" data-placement="top" data-original-title="Delete row" @click="deleteModalOpened(item)">
                                            <i class="fa fa-trash-o"></i>
                                        </button>
                                    </td>
                                </tr>
                            </tbody>
                        </table>

                        <!-- PAGINATION START -->
                        <div class="dataTables_info" role="status" aria-live="polite" v-if="resultCount > 0"  v-cloak>
                            Showing ${ currentCountFrom } to ${ currentCountTo } of ${ resultCount } entries
                        </div>

                        <div class="dataTables_paginate paging_simple_numbers" id="datatable_paginate" v-if="resultCount > 0">
                            <a class="paginate_button previous disabled" @click="previousPage()" v-if="currentPage==0">
                                <i class="fa fa-angle-left"></i>    
                            </a>
                            <a class="paginate_button previous" @click="previousPage()" v-else>
                                <i class="fa fa-angle-left"></i>    
                            </a>

                            <span v-for="pageNumber in totalPages">
                                <a class="paginate_button current" @click="setPage(pageNumber)" v-show="pageNumber == currentPage"  v-cloak>${ pageNumber + 1 }</a>
                                <a class="paginate_button" @click="setPage(pageNumber)" v-show="pageNumber != currentPage"  v-cloak>${ pageNumber + 1 }</a>
                            </span>

                            <a class="paginate_button next disabled" @click="nextPage()" v-if="currentPage == (totalPages - 1)">
                                <i class="fa fa-angle-right"></i>
                            </a>
                            <a class="paginate_button previous" @click="nextPage()" v-else>
                                <i class="fa fa-angle-right"></i>   
                            </a>
                        </div>
                        <!-- PAGINATION END -->
                    </div>
                </div>
            </div>
        </div>
    </form>
    <!-- BEGIN DATA TABLE END -->
</div>

<script>
    Vue.config.delimiters = ['${', '}'];

    new Vue({
        el: '#app',

        data: {
            items: [],
            columns: [                      
                {
                    key: 'id' ,
                    label: 'id' ,
                },                      
                {
                    key: 'title' ,
                    label: 'title' ,
                },                      
            ],

            // ALL PAGINATION VARS
            currentPage: 0,
            itemsPerPage: 20,
            resultCount: 0,
            totalPages: 0,
            currentCountFrom: 0,
            currentCountTo: 0,

            allSelected: false,
            cbIds: [],

            sortKey: '',
            isReversed: false
        },

        computed: {
            totalPages: function() {
                return Math.ceil(this.resultCount / this.itemsPerPage);
            },
            currentCountFrom: function () {
                return this.itemsPerPage * this.currentPage + 1;
            },
            currentCountTo: function () {
                var to = (this.itemsPerPage * this.currentPage) + this.itemsPerPage;
                return to > this.resultCount ? this.resultCount : to;
            }
        },

        ready: function() {
            this.pageUrl = '{{ path('items_ajax_list') }}';
            this.getVueItems();
        },

        filters: {
            paginate: function(list) {
                this.resultCount = this.items.length;

                if (this.currentPage >= this.totalPages) {
                  this.currentPage = Math.max(0, this.totalPages - 1);
                }

                var index = this.currentPage * this.itemsPerPage;

                return this.items.slice(index, index + this.itemsPerPage);
            }
        },

        methods : {
            sort: function (column) {
                if (column !== this.sortKey) {
                    this.sortKey = column;
                    this.items.sort(this.sortAlphaNum);
                    this.isReversed = false;
                    return;
                }

                this.reverse();

                if (this.isReversed) {
                    this.isReversed = false;
                }
                else {
                    this.isReversed = true;
                }
            },

            reverse: function () {this.items.reverse()},

            sortAlphaNum: function (a, b) {
                if (a[this.sortKey] === undefined) return;
                if (b[this.sortKey] === undefined) return;

                var cva = a[this.sortKey].toString().toLowerCase();
                var cvb = b[this.sortKey].toString().toLowerCase();

                var reA = /[^a-zA-Z]/g;
                var reN = /[^0-9]/g;

                var aA = cva.replace(reA, "");
                var bA = cvb.replace(reA, "");

                if(aA === bA) {
                    var aN = parseInt(cva.replace(reN, ""), 10);
                    var bN = parseInt(cvb.replace(reN, ""), 10);
                    return aN === bN ? 0 : aN > bN ? 1 : -1;
                } 

                return aA > bA ? 1 : -1;
            },

            setPage: function(pageNumber) {this.currentPage = pageNumber},

            nextPage: function () {
                if (this.pageNumber + 1 >= this.currentPage) return;
                this.setPage(this.currentPage + 1);
            },

            previousPage: function () {
                if (this.currentPage == 0) return;
                this.setPage(this.currentPage - 1);
            },

            getVueItems: function(page){
                this.$http.get(this.pageUrl)
                    .then((response) => {
                        var res = JSON.parse(response.data);
                        this.$set('items', res);
                    });
            },

        }
    });
    </script>

1 个答案:

答案 0 :(得分:1)

关于你的第一个问题,你可以在较小的数组中打破较大的数组,而不是以分页方式显示那些并对较小的数组进行排序,我创建了一个小提琴来演示它here

以下是在较小的数组中打破它的代码:

computed: {
  chunks () {
    var size = 2, smallarray = [];
    for (var i= 0; i<this.data.length; i+=size) {
       smallarray.push(this.data.slice(i,i+size))
            }
     return smallarray
  }
}

关于您的第二个问题,如果问题是在items调用后this.$http.get未正确填充,则可能是由于this变量的范围错误,这可能是如下更正:

getVueItems: function(page){
    var self = this
    this.$http.get(this.pageUrl)
        .then((response) => {
            var res = JSON.parse(response.data);
            self.items = res;
        });
},