Layui’s table component currently only supports single-column sorting, which is not able to support our business requirements in practical applications. Today, I decided to modify it to support multiple sorting.

The implementation idea is also relatively simple, just need to use an array to store all the sorted columns, and then pass the array to the back end (back-end sort) to sort. Following the general usage, hold down the Shift key and click on the table header to increase the number of rows, hold down the CTRL key and click on the table header to decrease the number of rows. Without further ado, here is the final image:

1. Define a sorted array

I’m currently using version 2.5.6, and the source code has been modified to accommodate business needs, so the number of lines described below is just a ballpark figure.

To accommodate single-column sorting, we added a configuration property for multiSort, which defaults to false and only enables multi-column sorting when it is true. Modify source code around line 235, add two properties multiSort, sortCols.

// constructor, Class = function (options) {var that = this; that.index = ++table.index; that.mutlSort = false; that.sortCols = []; Config = $.extend({}, that.config, table.config, options); that.render(); };Copy the code

2. Modify table header click events

Sort (asC, DESC); sort (asC, desc); We need to make a few changes here, increasing the order when shfit is pressed on the table header and decreasing the order when CTRL is pressed on the table header. Modified source code about 1511 lines

On ('click', function (e) {var othis = $(this), options = that.config, elemSort = othis.find(ELEM_SORT), nowType = elemSort.attr('lay-sort') , field = othis.data('field') , type; if (! elemSort[0] || resizing === 1) return resizing = 2; if (nowType === 'asc') { type = 'desc'; Else if (nowType === 'desc') {// type = null; //} else { type = 'asc'; } var sorts = JSON.parse(JSON.stringify(that.sortCols)); If (e.shiftkey) {var inArray = false; for (var i = 0; i < sorts.length; i++) { if (sorts[i].field == field) { sorts[i].type = type; inArray = true; break; } } if (! inArray) sorts.push({ field: field, type: type }); } else if (e.trlkey) {for (var I = 0; i < sorts.length; i++) { if (sorts[i].field == field) { sorts.splice(i, 1); break; }} else {// Single column sorts = [{field: field, type: type}]; } // single-column sort configuration if (! options.multiSort) sorts = [{ field: field, type: type }]; that.sort(sorts, null, true); }).find(ELEM_SORT + ' .layui-edge ').on('click', function (e) { var othis = $(this) , index = othis.index() , field = othis.parents('th').eq(0).data('field'); // Prevent events from bubbling.layui.stope (e); if (index === 0) { that.sort([{ field: field, type: 'asc' }], null, true); } else { that.sort([{ field: field, type: 'desc' }], null, true); }});Copy the code

3. Modify the table sorting method

Filed and Type signatures are used for multiple sorts. SortCols is used for multiple sorts.

Class.prototype.sort = function (sorts, pull, formEvent) {var that = this, res = {}, options = that.config, filter = options.elem.attr('lay-filter') , data = table.cache[that.key], thisData; // Render is not performed if (sorts. Length == that.sortcolls.length) {var sorted = true; for (var i = 0; i < sorts.length; i++) { if (sorts[i].field ! = that.sortCols[i].field || sorts[i].type ! = that.sortCols[i].type) { sorted = false; break; } } if (sorted) return; } tha.layheader.find ('th'). Each (function (I, item) {$(item).find(ELEM_SORT).removeattr ('lay-sort'); var field = $(item).data('field'); var cols = $.grep(sorts, function (obj) { return obj.field === field }); if (cols.length > 0) { $(item).find(ELEM_SORT).attr('lay-sort', cols[0].type || null); }}); delete that.sortCols; that.sortCols = sorts; // The default is front-end automatic sorting. If no, need to independent sort (usually a server handle sorting) if (options. AutoSort && sorts) {var clone = JSON. Parse (JSON. Stringify (data | | [])); clone.sort(function (dataRow1, dataRow2) { for (var i = 0, l = sorts.length; i < l; i++) { var field = sorts[i].field; var sign = sorts[i].type === 'asc' ? 1:1; var value1 = dataRow1[field], value2 = dataRow2[field]; var result = (value1 == value2 ? 0 : (value1 > value2 ? 1 : -1)) * sign; if (result ! = 0) { return result; } } return 0; }); thisData = clone; } / / data output form the if (options. AutoSort | |! formEvent) { res[options.response.dataName] = thisData || data; that.renderData(res, that.page, that.count, true); } if (formEvent) layui.event.call(that, MOD_NAME, 'sort(' + filter + ')', sorts); }; At the same time modify the source code about 686 lines: Class. Prototype. PullData = function (curr) {var that = this, options = that.config, request = options.request , response = options.response , sort = function () { if (typeof options.initSort === 'object') { //that.sort(options.initSort.field, options.initSort.type); that.sort(options.initSort); }}; // Here is... }Copy the code

4. Modify background parameters

The parameters passed to the background also need to be changed to arrays, and the code received by the back end also needs to be changed to receive arrays

Var layAttribute = self._$element.attr('lay-filter'); On ('sort(' + layAttribute + ')', function (obj) {var sortFilter = $.extend({}, kom.toJS(self.loadCondition || {})); Sortfilter.sorts = $.map(obj, elem => {return {fieldName: elem. Field, order: elem. Type}; }); Once again, / / a custom filter conditions if (self. The options. ParseFilter) sortFilter = self. Options. ParseFilter. Call (self, sortFilter); // Update the table component configuration self.options.where = sortFilter; self.table.config.where = sortFilter; self.table.inst.config.where = sortFilter; // Sort description self.options.initSort = obj; self.table.config.initSort = obj; self.table.inst.config.initSort = obj; Self.table.inst. pullData(self.table.inst.page); }); Public async Task<PagedList<Log>> GetPagedList([FromUri]Paging, [FromUri]Log condition, [FromUri]Sort[] sorts) { return await svc.GetPagedList(paging, condition, sorts); }Copy the code

So far, the whole transformation work is completed, the whole process is relatively simple. Mainly foot diligent and quick, want to be able to do.. . The domestic community of Layui is still quite mature, but I feel a little closed. I hope this domestic frame component will do better and go further and further.

The code is carried out separately and temporarily placed at github.com/TANZAME/TZM… Below, only do throw a brick to introduce jade, hope to have the help of the classmate who needs.

Technical exchange QQ group: 816425449