Search code examples
jquerybackbone.jsunderscore.jsbackbone-modeltypeerror

Backbone.js - Cannot read property 'Model' of undefined


I've been following this tutorial: http://backbonetutorials.com/organizing-backbone-using-modules/

The error is for line 7 of home.js (Model). What am I doing wrong???

main.js

// js/main.js

require.config ({
    paths: {
        // Include needed files.
        jquery: '//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min',
        underscore: '//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.6.0/underscore-min',
        backbone: 'libs/backbone/backbone.min'
    }
});

require([
    // Load app module and pass it
    // to the definition function.
    'app',
], function(App) {
    App.initialize();
})

app.js

// js/app.js

define ([
    'jquery',
    'underscore',
    'backbone',
    'router' // Request router.js
], function($, _, Backbone, Router) {
    var initialize = function() {
        Router.initialize();
    }
    return {
        initialize: initialize
    };
})

router.js

// js/router.js

define ([
    'jquery',
    'underscore',
    'backbone',
    'views/home'
], function($, _, Backbone, HomeView) {
    var AppRouter = Backbone.Router.extend({
        routes: {
            '': 'showHome'
        }
    });

    var initialize = function() {
        var app_router = new AppRouter;
        app_router.on('showHome', function() {
            var homeView = new HomeView;
            homeView.render();
        });
        Backbone.history.start();
    };

    return {
        initialize: initialize
    };
})

home.js (View)

// js/views/home.js

define ([
    'jquery',
    'underscore',
    'backbone',
    'collections/home',
    'text!/templates/home.html' // Use Require.js text plugin to load HTML file.
], function($, _, Backbone, HomeCollection, homeTemplate) {
    var HomeView = Backbone.View.extend({
        el: $('#home'),
        initialize: function() {
            this.collection = new HomeCollection();
            this.collection.add({name: "Ginger Kid"});

            var compiledTemplate = _.template(homeTemplate, {home: this.collection.models});

            // Append our compiled template to this Views "el".
            this.$el.append(compiledTemplate);
        }
    });

    return HomeView;
})

home.js (Model)

// models/home.js

define ([
    'underscore',
    'backbone'
], function($, _, Backbone) {
    var HomeModel = Backbone.Model.extend({
        defaults: {
            name: "Bob Smith"
        }
    });

    return HomeModel;
})

home.js (Collection)

// collections/home.js

define ([
    'underscore',
    'backbone',
    'models/home'
], function($, _, Backbone, HomeModel) {
    var HomeCollection = Backbone.Collection.extend({
        model: HomeModel
    });

    return HomeCollection;
})

Solution

  • The defines in your home collection are wrong.

    define ([
        'underscore',
        'backbone',
        'models/home'
    ], function($, _, Backbone, HomeModel) {
    

    Change to (you had a $ but weren't pulling in 'jquery':

    define ([
        'backbone',
        'models/home'
    ], function(Backbone, HomeModel) {
    

    Note that you don't need to include underscore and jQuery every time unless you are literally using them in that file (something starting with _. or $.). So you can remove those underscore and jquery defines in the other files too until you actually use them. See my note below on ensuring load order.

    Your model.js has the same problem:

    define ([
        'underscore',
        'backbone'
    ], function($, _, Backbone) {
    

    Change to (you had a $ but weren't pulling in 'jquery':

    define ([
        'backbone'
    ], function(Backbone) {
    

    Add this to your require config in main.js because it ensures that jquery and underscore are loaded first by saying they are a dependency of Backbone.

    shim: {
        backbone: {
            deps: [
                'underscore',
                'jquery'
            ],
            exports: 'Backbone'
        }
    }