Question

                    RoomsDGView = Backbone.View.extend({
                    collection: roomcollection,
                    initialize: function(){
                        var template = _.template( $("#search_template").html(), {} );
                        this.$el.html( template );
                        this.collection.bind('add', this.modeladded);
                        this.collection.bind('remove', this.modelremoved);
                        this.collection.bind('change', this.collectionchanged);
                        console.log(this);
                        this.render();
                    },
                    render: function(){
                        // Compile the template using underscore
                        console.log("running the render function...");
                        //renderrender();
                        /*$("#roomsList").jqGrid('clearGridData');
                        roomcollection.each(function (room,i){
                            var temp = jQuery.parseJSON(JSON.stringify(room));
                            $("#roomsList").jqGrid('addRowData', i,{idrooms: temp["idrooms"], roomname: temp["roomname"],
                            occupants: temp["occupants"]});
                        });*/
                    },
                    events: {
                        "click input[type=button]": "doSearch"  
                    },
                    doSearch: function(){
                        // Button clicked
                        console.log(this);
                    },
                    modeladded: function() {
                        console.log("room added...");
                        $("#roomsList").jqGrid('clearGridData');
                        //My intent is to call the views render function
                        //her. I tried using this.render() and also 
                        //this.collection.bind('add', this.modeladded(this));
                        //modeladded: function(view) {
                        //     view.render();
                        console.log(this);
                    },
                    modelremoved: function() {
                        console.log("room removed...");
                        $("#roomsList").jqGrid('clearGridData');
                    },
                    collectionchanged: function() {
                        console.log("room changed...");
                        $("#roomsList").jqGrid('clearGridData');
                    }
                });

I have tried many different ways to call the views render: method from inside the code for modeladded:. Use of this.render inside model added shows that the this object at that point has no render function. I also tried passing the view in something like:

this.collection.bind('add', this.modeladded(this));

modeladded: function(view) { view.render();

which also leads to a console error that no render() can be found. Does anyone know how to call the views render: from inside modeladded?

For the time being I moved the render function out of the views render: and into a JavaScript function declared renderGlobal() declared in global scope and I know it does work that way but I don't think that is really the backbone.js way.

This is the error that is coming out of the console: Uncaught TypeError: Object [object Object] has no method 'render'

Thank you for posting....

Was it helpful?

Solution

You're binding your event handler using bind (AKA on):

this.collection.bind('add', this.modeladded);

But, as usual with JavaScript, the value of this inside a function depends on how the function is called, not how it is defined (ignoring bound functions of course). You're not specifying a specific this for your function anywhere so you're not getting any particular this when it is called. If you give bind the third context argument:

this.collection.bind('add', this.modeladded, this);
// ------------------------------------------^^^^

then Backbone will call modeladded with the specific this and you'll find that this inside modeladded will be your view.

You could also use _.bind, Function.prototype.bind, or $.proxy to produce a bound version of your callback:

this.collection.bind('add', _(this.modeladded).bind(this));
this.collection.bind('add', this.modeladded.bind(this));
this.collection.bind('add', $.proxy(this.modeladded, this));

All of those produce new functions so you won't be able to unbind them without stashing the bound functions somewhere. You'll usually avoid using these when you have the option to specify the context (AKA this) explicitly.

There's also listenTo:

listenTo object.listenTo(other, event, callback)

Tell an object to listen to a particular event on an other object. The advantage of using this form, instead of other.on(event, callback, object), is that listenTo allows the object to keep track of the events, and they can be removed all at once later on. The callback will always be called with object as context.

So you can (and should) say this:

this.listenTo(this.collection, 'add', this.modeladded);

That will take care of giving you the desired this and makes it easier to clean up your event handlers when you're done with them. Similarly for the other event handlers you're using.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top