Search code examples
backbone.jsbackbone-viewsbackbone-events

what is the correct way to get element from collection


In my backbone view, I am getting models from my collection..

initialize:function(){
    this.collection = new collection(student);
    this.render();
},

from this collection I am filtering the high value models using filter method:(on click I am triggering)

getHighSocre:function(){
    return _.filter(this.collection.models, function(item){
         return parseInt(item.get('scored')) > 60
    })
},
showHighScore:function(){
    var hView = new studentView({model:this.getHighSocre()}); // sending to single view
    hView.showMe(); // I am calling this method to add a class name to each 'li' element..
}

here is my single view:

var studentView = Backbone.View.extend({
    tagName:'li',
    events:{
        'click':"called"
    },
    template:_.template($("#studentTemplate").html()),
    render:function(){
        this.$el.append(this.template(this.model.toJSON()));
        return this;
    },
    called:function(){
        if(this.model.get('scored') > 60){
            this.$el.css({
                background:"#EFEFEF"
            })
        }else{
            this.$el.css({
                background:"#FCBABA"
            })
        }

    },

    showMe:function(){ // I am passing here to add a class name

        console.log(this) // make the array... here

        this.$el.css({ // but this is not getting the dom element...
             border:'1px solid red'
         })
     }
});

How to I add the class name to each of this li elements? What is wrong here, anyone can help me to sort or can give me a correct way to filter a collection and apply the class name to it's element?

Here is the jsfiddle.


Solution

  • First off, with Backbone and Underscore, you usually don't want to call Underscore methods on Collections, eg:

    _.filter(this.collection.models, function(item){
    

    you instead want to call the Backbone Collection equivalent method (http://documentcloud.github.io/backbone/#Collection-Underscore-Methods):

    this.collection.filter(function(item){
    

    Second you misspelled "score" as "socre"; not trying to be a jerk, just pointing it out because such misspellings can easily cause bugs.

    Third, views expect a model for their model parameter, but your getHighSocre method returns the result of a filter, ie. an array of models, so this line:

    new studentView({model:this.getHighSocre()});
    

    isn't going to work. If you just want the first model with a score above 60, try using find instead of filter, and if you really do want your view to have every model with a score above 60 then you probably want to convert those models in to a new collection and pass that as the view's collection (rather than as its model).

    P.S.

    This isn't really part of the answer, but just a note; if you weren't familiar with Javascript's ternary operator, you might want to check it out as it lets you reduce all of this:

        if(this.model.get('scored') > 60){
            this.$el.css({
                background:"#EFEFEF"
            })
        }else{
            this.$el.css({
                background:"#FCBABA"
            })
        }
    

    to just:

    var isAbove60 = this.model.get('scored') > 60;
    this.$el.css('backgroundColor', isAbove60 ? "#EFEFEF" : "#FCBABA");