javascript - Re-sorting backbone collection from view - Stack Overflow

I'm having problems resorting my collection upon a click event. The sorting function is triggered

I'm having problems resorting my collection upon a click event. The sorting function is triggered and executes for each model but neither the reset event is gets triggered nor the collection changes on the view.

I have multiple sort criterias defined on my collection like:

feNoRequire.Collections.CompetitionCollection = Backbone.Collection.extend({

    model: feNoRequire.Models.CompetitionModel,
    parator: function (property) {
        return selectedStrategy.apply(model.get(property));
    },
    strategies: {
        name: function (petition) { return petition.get("name"); }, 
        nameReverse: function (petition) { console.log(petition); return -petition.get("name"); }, 
        date: function (petition) { console.log(petition.get("event")); },
    },
    changeSort: function (sortProperty) {
        thisparator = this.strategies[sortProperty];
    },
    initialize: function () {
        this.changeSort("name");   
    }

});

And on my view file:

initialize: function(options){
        this.evnt = options.evnt;

        this.collection.on('reset', this.render, this);     
        this.evnt.bind("orderByDate", this.changeSort, this);
    },

    changeSort: function(){
        this.collection.changeSort('nameReverse')
        this.collection.sort();
    },

    render: function() {
        console.log("going for rendering")
        var renderedContent = this.template({petitions: this.collection.toJSON()});

        $(this.el).html(renderedContent);
        return this;
    }

Any idea on how to solve this?

EDIT After the answers bellow the render is now triggered but the objected only get sorted on initialize. Any subsequent sorts return the collection in the initial order - this.changeSort("name");

my model:

feNoRequire.Models.CompetitionModel = Backbone.Model.extend({
    initialize: function(){
        this.attributes.events = new feNoRequire.Collections.EventCollection(this.attributes.events);
    }
});

I'm having problems resorting my collection upon a click event. The sorting function is triggered and executes for each model but neither the reset event is gets triggered nor the collection changes on the view.

I have multiple sort criterias defined on my collection like:

feNoRequire.Collections.CompetitionCollection = Backbone.Collection.extend({

    model: feNoRequire.Models.CompetitionModel,
    parator: function (property) {
        return selectedStrategy.apply(model.get(property));
    },
    strategies: {
        name: function (petition) { return petition.get("name"); }, 
        nameReverse: function (petition) { console.log(petition); return -petition.get("name"); }, 
        date: function (petition) { console.log(petition.get("event")); },
    },
    changeSort: function (sortProperty) {
        this.parator = this.strategies[sortProperty];
    },
    initialize: function () {
        this.changeSort("name");   
    }

});

And on my view file:

initialize: function(options){
        this.evnt = options.evnt;

        this.collection.on('reset', this.render, this);     
        this.evnt.bind("orderByDate", this.changeSort, this);
    },

    changeSort: function(){
        this.collection.changeSort('nameReverse')
        this.collection.sort();
    },

    render: function() {
        console.log("going for rendering")
        var renderedContent = this.template({petitions: this.collection.toJSON()});

        $(this.el).html(renderedContent);
        return this;
    }

Any idea on how to solve this?

EDIT After the answers bellow the render is now triggered but the objected only get sorted on initialize. Any subsequent sorts return the collection in the initial order - this.changeSort("name");

my model:

feNoRequire.Models.CompetitionModel = Backbone.Model.extend({
    initialize: function(){
        this.attributes.events = new feNoRequire.Collections.EventCollection(this.attributes.events);
    }
});
Share Improve this question edited May 4, 2013 at 17:34 jribeiro asked May 4, 2013 at 15:00 jribeirojribeiro 3,4939 gold badges45 silver badges70 bronze badges 3
  • 'this.attributes.events = new feNoRequire.Collections.EventCollection(this.attributes.events);' <- out of curiousity, what's the purpose of this? – 1nfiniti Commented May 5, 2013 at 4:19
  • For each model, I have a list of events which I want to be models as well so I can sort them. – jribeiro Commented May 5, 2013 at 12:34
  • a late ment, for sure, but semantically, I would move the manual call to this.collection.sort() in the View.changeSort into the Collection's function, via this.sort(); this way you know when you call changeSort() on the collection, it will always re-sort itself. – mix3d Commented Sep 21, 2016 at 3:23
Add a ment  | 

3 Answers 3

Reset to default 6

From the fine manual:

sort collection.sort([options])

[...] Calling sort triggers a "sort" event on the collection.

So calling sort doesn't trigger a "reset" event (because the collection doesn't get reset), it triggers a "sort" event. So you want to:

this.collection.on('sort', this.render, this);

as well as binding to "reset".

Demo: http://jsfiddle/ambiguous/34Ena/


I see that you're calling changeSort('nameReverse') and that that sorting does this:

nameReverse: function (petition) {
    return -petition.get("name");
}

That won't do what you think it does, negating a non-numeric string will give you NaN. That means that you'll end up trying to sort a list of NaNs and all of these are false:

NaN  < NaN
NaN  > NaN
NaN == NaN

so sorting a list of NaNs does nothing useful. You'll have to use a two argument parator function if you want to reverse sort strings:

nameReverse: function(a, b) {
    a = a.get('name');
    b = b.get('name');
    return a < b ?  1
         : a > b ? -1
         :          0;
}

You may listen to collection's sort event and perform render. Try changing event binding to:

this.collection.on('sort reset', this.render, this);     

Very nice code setup. I really like the way you're calling your sort functions via the strategies object.

I think the issue with this code is stemming from the following section:

parator: function (property) {
    return selectedStrategy.apply(model.get(property));
},

as per the documentation, the parator function takes a model or iterator (not a property), also not sure what selectedStrategy is supposed to be referencing... is this another function that exists somewhere outside the code you've provided?

Apply also takes a context object to act as "this", and an array of arguments. As per the MDN documentation on apply:

fun.apply(thisArg[, argsArray])

unless your model's property is an object that you want to use as "this", i don't see this working properly. Maybe it would make more sense if I could see the model definition as well.

EDIT: After reading the other responses that came in, I realized you're watching the reset event instead of the sort, so my response is probably just a misunderstanding of your code, and not the problem afterall :)

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744119481a4559330.html

相关推荐

  • javascript - Re-sorting backbone collection from view - Stack Overflow

    I'm having problems resorting my collection upon a click event. The sorting function is triggered

    8天前
    10

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信