Cody Hatch
Cody Hatch

Reputation: 8937

How do I bind an event to a model that isn't loaded yet?

So I've got a pretty simple backbone app with a model, a collection, and a couple of views. I'm fetching the actual data from the server by doing a collection.fetch() at page load.

My problem is that one of my views is a "detail" view, and I want to bind it to a particular model - but I don't have the model yet when the page loads. My code looks a lot like this:

window.App = {
    Models: {},
    Collections: {},
    Views: {},
    Routers: {}
}

App.Models.Person = Backbone.Model.extend({
    urlRoot: '/api/people'
});

App.Collections.People = Backbone.Collection.extend({
    model: App.Models.Person,
    url: '/api/people'
});

people = new App.Collections.People()

App.Views.List = Backbone.View.extend({
    initialize: function() {
        this.collection.bind('reset', this.render());
    },
    render: function() {
        $(this.el).html("We've got " + this.collection.length + " models." )
    }
});

listView = new App.Views.List({collection: people})

App.Views.Detail = Backbone.View.extend({
    initialize: function() {
        this.model.bind('change', this.render());
    },
    render: function() {
        $(this.el).html("Model goes here!")
    }
});

App.Routers.Main = Backbone.Router.extend({
    routes: {
        '/people': 'list',
        '/people/:id': 'detail'
    },
    list: function() {
        listView.render();
    },
    detail: function(id) {
        detailView = new App.Views.Detail({model: people.get(id)})
        detailView.render()
    }
})

main = new App.Routers.Main();
Backbone.history.start();
people.fetch();

But if I start with the detail route active, the people collection is empty, so people.get(id) doesn't return anything, so my new view has this.model undefined, and won't let me bind any events relating to it. The error is:

Uncaught TypeError: Cannot call method 'bind' of undefined

If I start with the list route active, then by the time I click on an item to bring up the detail view people is populated, so everything works.

What's the right way to bind model-related events for a "detail" view when you're fetching the data after page load?

Upvotes: 0

Views: 655

Answers (1)

Atinux
Atinux

Reputation: 1703

You have a part of the answer here: Backbone.js Collections not applying Models (using Code Igniter)

Indeed, you need to wait that people.fetch finishes its ajax request before to call Backbone.history.start(); and trigger the actual route.

Your code should look like:

// [...]
main = new App.Routers.Main();
peoples.fetch({
    success: function (collection, response) {
        // The collection is filled, trigger the route
        Backbone.history.start();
    }
});

You can add a loader on the page and hide it when the collection is loaded.

Upvotes: 1

Related Questions