Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

backbone.js collection not responding to .each

I have what should be very simple. I create a new collection, and I want to pass it to a render and add the collection models to the page.

get_results: function(){
    $.getJson(this.url,function(response){
        this.search_results = new Kitchon.Collections.searchList(response);
        console.log(this.search_results);
        this.search_results.each(this.render_match);
    }
},
render_match: function(model){
    console.log(model)
},

This returns an error

Uncaught TypeError: undefined is not a function

my collection has an ordinary structure

_byCid: Object
_byId: Object
_onModelEvent: function () { [native code] }
_removeReference: function () { [native code] }
length: 7
models: Array[7]
__proto__: o

I've tried LOTS of things, but one thing that stuck out was maybe I had to pass this.search_results.models.each(this.render_match); as that is the actual array, but if I do that I get a Uncaught typeError: Object [object Object],[object Object],...

like image 230
pedalpete Avatar asked Feb 22 '23 20:02

pedalpete


2 Answers

you lose the execution context when callback function for each method is called

use _.bind(this.render_match, this) when passing callback to make sure that render_match has the right context

and you were getting error because you didn't wrap the callback function for getJson method neither. You have to use underscore bind method there as well.

You should read a bit about javascript this and how to tame it - try here http://yehudakatz.com/2011/08/11/understanding-javascript-function-invocation-and-this/

Correct code should look more or less like this...

get_results: function(){

    $.getJSON(this.url, _.bind(function(response){

        this.search_results = new Kitchon.Collections.searchList(response);
        console.log(this.search_results);
        this.search_results.each(_.bind(this.render_match, this));
    }, this));
},
render_match: function(model){

    console.log(model)
},

Though from what I seee - I assume the code you've shown here is either a model or collection - is handling rendering the view - you shouldn't do that! Models and Collections are only to store and parse data - all rendering and controlling application flow should be done in the View(Controllers) with help of the Router.

like image 190
Tom Tu Avatar answered Mar 05 '23 08:03

Tom Tu


$.getJson changes the this reference. Many methods in jquery do that, so the value of this.render_match is null. You pass null to each and it fails.

To solve that, create a reference to this (like var _this = this;) before $.getJson and use it instead of this. Code should be like below:

get_results: function(){
    var _this = this;
    $.getJson(this.url,function(response){
        _this.search_results = new Kitchon.Collections.searchList(response);
        console.log(_this.search_results);
        _this.search_results.each(_this.render_match);
    }
},
render_match: function(model){
    console.log(model)
},
like image 37
Marcelo Diniz Avatar answered Mar 05 '23 08:03

Marcelo Diniz