简体   繁体   English

底部带有空格的日期的Javascript自定义排序功能

[英]Javascript custom sort function for dates with blanks at the bottom

I am using a table plugin (ng-grid) to display a bunch of data which includes some date columns. 我正在使用表格插件(ng-grid)显示一堆数据,其中包括一些日期列。 The plugin allows custom sorting with a "sortingAlgorithm" function, which accepts "aDate" and "bDate" parameters. 该插件允许使用“ sortingAlgorithm”函数进行自定义排序,该函数接受“ aDate”和“ bDate”参数。 The dates are stored as strings in the database, and I'm using Moment to convert them to date objects. 日期以字符串形式存储在数据库中,我正在使用Moment将其转换为日期对象。 Here is the sort function: 这是排序功能:

sortingAlgorithm: function (aDate, bDate) {
    var a = moment(aDate, 'MM/DD/YYYY');
    var b = moment(bDate, 'MM/DD/YYYY');
    if (a.isBefore(b)) {
        return -1;
    }
    else if (a.isAfter(b)) {
        return 1;
    }
    else {
        return 0;
    }
}

This works fine, but if there is no date, just an empty string, the blanks are going at the end of the list when sorted in ascending order, but at the beginning when sorted descending. 这可以正常工作,但是如果没有日期,只是一个空字符串,则空格按升序排列在列表的末尾,而按降序排列在开始的末尾。 What can I do to ensure that blanks ("") are always moved to the bottom of the list? 如何确保空白(“”)始终移到列表的底部?

Thanks. 谢谢。

UPDATE 更新

I think this has something to do specifically with the UI-Grid library. 我认为这与UI-Grid库特别相关。 See rowSorter.js . 参见rowSorter.js It seems to handle nulls internally, which is gumming up my mojo. 它似乎在内部处理null,这使我的mojo感到困惑。 I also don't see where the selected sort direction is exposed for me to work with... 我也看不到选择的排序方向暴露在什么地方供我使用...

I'm adding the "angular-ui-grid" tag... 我正在添加“ angular-ui-grid”标签...

So I took a copy of ui-grid's internal date-specific sorting function, and replaced their "handleNulls" function call with my own (see below): 因此,我复制了ui-grid内部特定于日期的排序函数,并用我自己的函数替换了其“ handleNulls”函数调用(请参见下文):

sortingAlgorithm: function (a, b) {
    var nulls = handleNulls(a, b);
    if ( nulls !== null ){
        return nulls;
    } else {
        if (!(a instanceof Date)) {
            a = new Date(a);
        }
        if (!(b instanceof Date)){
            b = new Date(b);
        }
        var timeA = a.getTime(),
            timeB = b.getTime();

        return timeA === timeB ? 0 : (timeA < timeB ? -1 : 1);
    }
}

And here is a copy of ui-grid's "handleNulls" function, updated to always force nulls to the bottom based on the direction: 这是ui-grid的“ handleNulls”函数的副本,已更新为始终根据方向将空值强制到底部:

function handleNulls(a, b) {
    if ((!a && a !== 0 && a !== false) || (!b && b !== 0 && b !== false)) {
        if ((!a && a !== 0 && a !== false) && (!b && b !== 0 && b !== false)) {
            return 0;
        }
        else if (!a && a !== 0 && a !== false && vm.direction === 'asc') {
            return 1;
        }
        else if (!b && b !== 0 && b !== false && vm.direction === 'asc') {
            return -1;
        }
        else if (!a && a !== 0 && a !== false && vm.direction === 'desc') {
            return -1;
        }
        else if (!b && b !== 0 && b !== false && vm.direction === 'desc') {
            return 1;
        }
    }
    return null;
};

vm.direction comes from ui-grid's onRegisterApi callback, which has a hook for sort changes: vm.direction来自ui-grid的onRegisterApi回调,该回调具有用于进行排序更改的钩子:

onRegisterApi: function (gridApi) {
    vm.gridApi = gridApi;
    vm.gridApi.core.on.sortChanged($scope, function(grid, sortColumns) {
        if (sortColumns[0]) {
            vm.direction = sortColumns[0].sort.direction;
        } else {
            vm.direction = 'none';
        }
    });
}

Works like a charm! 奇迹般有效!

If the ng-grid plugin uses the sorting algorithm and then applies a reverse() to sort in descending order, then I don't think you can force the items at the end. 如果ng-grid插件使用排序算法,然后应用reverse()以降序排序,那么我认为您不能在项目末尾强制使用。 You would have to overwrite the sorting in the plugin I guess. 我猜您将不得不覆盖插件中的排序。

In order to test for empty string, you could put your comparison condition first and so '' is always at the end. 为了测试空字符串,您可以将比较条件放在第一位,因此''总是结尾”。 This way you are not creating an invalid date by forcing moment.js to parse an empty string. 这样,您不会通过强制moment.js解析空字符串来创建无效日期。

sortingAlgorithm: function(aDate, bDate) {
  if (aDate === '') {
    return 1;
  }
  if (bDate === '') {
    return -1;
  }

  var a = moment(aDate, 'MM/DD/YYYY');
  var b = moment(bDate, 'MM/DD/YYYY');

  if (a.isBefore(b)) {
    return -1;
  } else if (a.isAfter(b)) {
    return 1;
  } else {
    return 0;
  }
}

Try this: 尝试这个:

var direction=1;
var sortingAlgorithm= function (aDate, bDate) {
    var a=moment(aDate,'MM/DD/YYYY');
    var b=moment(bDate,'MM/DD/YYYY');
    if (!a.isValid()) return 1;
    if (!b.isValid()) return -1;
    return direction*((+a)-(+b));
}

It takes into account the validity of the date and direction (1 or -1), so that the invalid dates are always at the bottom. 它考虑了日期和方向(1或-1)的有效性,因此无效日期始终在底部。

Here is what I came up with based on this and another thread using moment.js 这是我基于此和另一个使用moment.js的线程得出的结果

 var sortmedate = function (a, b, rowA, rowB, direction) {
            //the dates do not get sorted properly so we need moment.js and this method.
            var dateFormat = 'MM/DD/YYYY'; //todo: pass in date format from mvc controller.

            if (!a && !b) {
                return 0;
            }

            if (!a) {
                return 1;
            }

            if (!b) {
                return -1;
            }

            var firstDate = moment(a, dateFormat);
            if (!firstDate.isValid()) {
                return -1;
            }

            var secondDate = moment(b, dateFormat);
            if (!secondDate.isValid()) {
                return 1;
            }

            if (firstDate.isSame(secondDate)) {
                return 0;
            } else {
                return firstDate.isBefore(secondDate) ? -1 : 1;
            }

        };

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM