weixin_39991926
2020-12-02 23:21 阅读 1

custom comparator

Question: what would be the canonical approach to implementing a custom sort comparator for PageableCollections in Client mode? Looking to use an ignoreCase sorting fn for strings. Tried overriding the comparator in the collection def, but it seems to fallback to native or _cid sorting. Tried to extend the HeaderCell view and pass in a new comparator def there, but not yet successful. What would be your approach? Many thanks!

该提问来源于开源项目:cloudflarearchive/backgrid

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享

25条回答 默认 最新

  • weixin_39776787 weixin_39776787 2020-12-02 23:21

    Each cell in my grid can be a string, JSON object, or array, so I definitely needed a custom comparator - I ran into similar issues and ended up just having to modify the _makeComparator function in backbone-pageable.js. Probably not the "right" way to do it, but it worked for me...

    I'd love to hear solutions from others who've done a custom comparator.

    点赞 评论 复制链接分享
  • weixin_39866265 weixin_39866265 2020-12-02 23:21

    has asked a similar question recently: https://github.com/wyuenho/backbone-pageable/issues/89

    This seems to be a recurring issue for a couple of people of late. Suggestions on how to improve this is welcomed.

    点赞 评论 复制链接分享
  • weixin_39562579 weixin_39562579 2020-12-02 23:21

    This may be a bit off topic, but I simply want case insensitive column sorting.

    I would prefer to have "comparator : function(a,b){...}" as a column option, but any hints on how to do this without modifying backgrid would be appreciated.

    点赞 评论 复制链接分享
  • weixin_39708708 weixin_39708708 2020-12-02 23:21

    The problem I see with passing a custom comparator function is that it depends on the column. It would have to be a dumbed down comparator that doesn't consider left and right as models, but as attributes.

    点赞 评论 复制链接分享
  • weixin_39562579 weixin_39562579 2020-12-02 23:21

    What about passing sorting: 'caseinsensitive' | 'numeric' | 'date' instead? It's not as flexible, but it would save my day. ;-)

    点赞 评论 复制链接分享
  • weixin_39866265 weixin_39866265 2020-12-02 23:21

    How about this?

     javascript
    columns: [
      name: "name",
      label: "Name",
    
      // Put your custom logic that returns a comparator function based on the direction here
      // Similar to Backbone.PagableCollection#_makeComparator
      comparatorProvider: function (attr, order) {
        return function (left, right) {
    
          // no-op
          if (order == null) return 0;
    
          var l = left.get(attr), r = right.get(attr), t;
    
          // if descending order, swap left and right
          if (order === 1) t = l, l = r, r = t;
    
          // compare as usual
          if (l === r) return 0;
          else if (l < r) return -1;
          return 1;
        }
      }
    ]
    

    This should help folks who are dealing with nested data who only have Formatters to use to display them but not sort them.

    点赞 评论 复制链接分享
  • weixin_39708708 weixin_39708708 2020-12-02 23:21

    This could work, but why would this logic (the swapping of left and right) ever change? Why not have it built in inside HeaderCell?. Let me build up a commit real fast, I'll show you what I mean.

    点赞 评论 复制链接分享
  • weixin_39866265 weixin_39866265 2020-12-02 23:21

    Are you thinking of a function that lets you extract the values from the models?

    点赞 评论 复制链接分享
  • weixin_39708708 weixin_39708708 2020-12-02 23:21

    What do you think of something like that? Keep in mind this is not tested at all, just a quick mockup.

    点赞 评论 复制链接分享
  • weixin_39708708 weixin_39708708 2020-12-02 23:21

    The only ambiguity I see with this is that the comparator option you would pass to the HeaderCell is not a typical Backbone.Collection comparator. it's a generic version that compares the two raw values instead of the two models.

    点赞 评论 复制链接分享
  • weixin_39708708 weixin_39708708 2020-12-02 23:21

    Also see this commit: wyuenho/backbone-pageable

    点赞 评论 复制链接分享
  • weixin_39866265 weixin_39866265 2020-12-02 23:21

    I'm thinking along similar lines. I think most people will only have trouble with this line:

     javascript
    var l = left.get(attr), r = right.get(attr), t;
    

    That's pretty much the only line they'll have to customize, the rest should be the same for everyone. How about just a value extractor that you can provide to the column definition?

    BTW, that commit you just posted looks like it's coming from backbone-pageable's repo, how did you do that?

    点赞 评论 复制链接分享
  • weixin_39708708 weixin_39708708 2020-12-02 23:21

    How about just a value extractor that you can provide to the column definition?

    Are you talking about something like this?

     javascript
    var l = left.get(this.column.modelAttribute()), r = right.get(this.column.modelAttribute())
    

    BTW, that commit you just posted looks like it's coming from backbone-pageable's repo, how did you do that?

    The same way you linked to the backbone-pageable issue, except you replace the issue number (#89) with @ followed by the commit hash (``) !

    点赞 评论 复制链接分享
  • weixin_39562579 weixin_39562579 2020-12-02 23:21

    Why is it a problem to supply a simple, classic comparator function?

    
    function compare(a, b) {
        if (a.toString() < b.toString()) return -1;
        if (a.toString() > b.toString()) return 1;
        return 0;
    }
    
    点赞 评论 复制链接分享
  • weixin_39866265 weixin_39866265 2020-12-02 23:21

    Something like this:

     javascript
    columns: [
      name: "name",
      label: "Name",
      value: function (model, attr) {
        return model.get(attr).b.c[3];
      }
    ]
    

    The value will be used as the left and right values for the comparator generated automagically by HeaderCell.

    If not supplied, the value function will default to:

     javascript
    function (model, attr) {
     return model.get(attr);
    }
    
    点赞 评论 复制链接分享
  • weixin_39708708 weixin_39708708 2020-12-02 23:21

    So everywhere that model.get(column.get("name")) is used will be changed to this? If so, what about the other way around, will you have a value injector?

    点赞 评论 复制链接分享
  • weixin_39866265 weixin_39866265 2020-12-02 23:21

    No. Only when extracting the attribute value for sorting. You already have formatters that you can override to process nested data.

    点赞 评论 复制链接分享
  • weixin_39991926 weixin_39991926 2020-12-02 23:21

    I'm starting to like your idea of defining the sort value/attr in the column/cell def. I was trying to pass that into the comparator factory.

    I took the approach of extending the HeaderCell with a custom comparator, in my case was for Ignore Case + Nulls Last. So it started looking like...

     javascript
    var IgnoreCaseHeaderCell = Backgrid.HeaderCell.extend({
      sort: function(columnName, direction){
        return Backgrid.HeaderCell.prototype.sort.call(this, columnName, direction, ignoreCaseSortMaker(columnName, direction));
      }
    }); 
    

    and the ignoreCase factory started looking like:

     javascript
    var ignoreCaseSortMaker = function(attr, direction) {
      return function (a, b) {
        var left  = a.get(attr);
        var right = b.get(attr);
        var order;
    
        if (direction === "ascending") order = -1;
        else if (direction === "descending") order = 1;
        else order = null;
    
        // no-op
        //if (order === null) return 0;
    
        if (_.isUndefined(left)) { return 1; }
        else if (_.isUndefined(right)) { return 1; }
    
        var l = left[0], r = right[0], t;
    
        // if descending order, swap left and right
        if (order === 1) t = l, l = r, r = t;
    
        if (l === r) return 0;
    
        if (_.isString(l)) {
          l = l.toLowerCase();
          r = r.toLowerCase();
        }
    
        return l < r ? -1 : 1;
      };
    };
    

    i'm not sure the logic is working correctly here. but the issue i see is the sort doesn't kick in until the 3rd header sort click, or when direction is removed...and then it blows up. And the 1st and 2nd header sort clicks are hitting the default comparators instead. With sort methods being defined in multiple places (header and pageable extensions) it's challenging to hit on a single fix for this.

    and of course i set the respective header in the col def depending on cell type. sort of like:

     javascript
    ...
    {"name": blah, 
     "label": blah, 
     "cell": blah_type, 
     "headerCell": (blah_type === "string" ? IgnoreCaseHeaderCell : Backgrid.HeaderCell), 
     "editable": blah || false
    }, ...
    
    点赞 评论 复制链接分享
  • weixin_39708708 weixin_39708708 2020-12-02 23:21

    Ok I see what you mean. Makes sense. Also, concerning the Backbone.Pageable commit, it's because the commit is directly on the Backbone.Pageable repo, not on Backgrid's version of the lib!

    点赞 评论 复制链接分享
  • weixin_39866265 weixin_39866265 2020-12-02 23:21

    I know I know I have a fix for this and the sortable: "somestring" in a few days. Feel free to send over a PR if you are impatient.

    点赞 评论 复制链接分享
  • weixin_39562579 weixin_39562579 2020-12-02 23:21

    Yes, this seems perfect.

     javascript
    var comparator = function(left, right) {
          var l = left.toLowerCase(), r = right.toLowerCase();
          if(l === r) return 0;
          if(l < r) return -1;
          return 1;
        };
    
        cell = new Backgrid.HeaderCell({
          collection: words,
          column: {
            name: "name",
            cell: "string",
            comparator: comparator
          }
        });
    
    点赞 评论 复制链接分享
  • weixin_39866265 weixin_39866265 2020-12-02 23:21

    Reopening until I'm done moving things around...

    点赞 评论 复制链接分享
  • weixin_39524636 weixin_39524636 2020-12-02 23:21

    How can we find out what library or libraries need to be updated in order to utilize the new sorting changes? I updated just backbone-pageable.js and now the paginator links are broken. When I click on a page other than page 1, it moves to the page, but the 1 remains highlighted. I'm not sure if there's something else I need to do/update or if it's a bug..

    点赞 评论 复制链接分享
  • weixin_39866265 weixin_39866265 2020-12-02 23:21

    According to #231 this issue is fixed if you update to the latest paginator extension from master. Ping me on #231 if it doesn't work out for you.

    I'll release 0.3 this week. Will document an upgrade path.

    点赞 评论 复制链接分享
  • weixin_39778447 weixin_39778447 2020-12-02 23:21

    I just started using Backgrid, and need to exclude group-headings while sorting. Please help.

    Regards, Vikram

    点赞 评论 复制链接分享

相关推荐