Dan
Dan

Reputation: 1051

Unable to Create Backbone View

I'm continually getting index.js:7 Uncaught TypeError: Cannot read property 'View' of null, which indicates that Backbone is not loaded/present, however, when I review the loaded resources on the page backbone-min.js is present.

Since there are no 404 errors, I believe the issue is with the script itself. Does anyone see any issues with the script below?

NOTE: For convenience I uploaded my code here. The zip file contains all the relevant js files. If you scroll to the bottom of the webpage, you should see a "slow download" button, once you click it you'll be prompted to enter a captcha code. After entering the code, the actual download button (under the "slow download" button) will appear within a few seconds.

View: index.js

define([
        "jQuery",
        "Underscore",
        "Backbone"
        // I've tried using the modules above as well as direct loading using order! as seen in the following lines.
        //"order!libs/jquery/jquery-min",
        //"order!libs/underscore/underscore-min",
        //"order!libs/backbone/backbone-min",
        ], 
        function($, _, Backbone){
            console.log(_) // prints "undefined"
            console.log(Backbone) // prints Object
            var IndexView = Backbone.View.extend({ // At this line I now get: Uncaught TypeError: Cannot call method 'extend' of undefined
                render: function(){
                    $(this.el).html("<h1>Welcome Dan!</h1>");
                    $("body").html(this.el);
                }
            });
            return new IndexView();
        });

Upvotes: 3

Views: 5301

Answers (2)

mfalto
mfalto

Reputation: 405

So the key to this issue is changes in underscore.js. Specifically the fact it now supports AMD (Asynchronous Module Definition). The fact that underscore no longer attaches itself to the global namespace when require is detected is breaking the scheme used to allow a standard asynchronous require syntax but still maintain synchronous loading.

Now that JQuery, Underscore & Backbone (0.5.3 does not register itself, you need a this) support async loading, you are able to abandon those hacked libraries in favor of the standard ones and require the names those libraries register themselves with. Like this:

Main.js

require.config({
    baseUrl: "js",
    paths: { 
               jquery: "libs/jquery/jquery",
               underscore: "libs/underscore/underscore",
               backbone: "libs/backbone/backbone"
           },
    waitSeconds: 10
});

require([
        "app"
        ],
        function(App){
            App.initialize();
            console.log("Main initialized...");
        });

index.js

define([
    "jquery",
    "underscore",
    "backbone"
    ], 
    function($, _, Backbone){
        console.log(_);
        console.log(Backbone);
        var IndexView = Backbone.View.extend({
            render: function(){
                var username = getCookie("username");
                var data = {username: username};
                var compiled = _.template("<h1>Welcome <%= username %></h1>", data);
                $(this.el).html(compiled);
                $("#lt-col").html(this.el);
            }
        });
        return new IndexView();
    });

Other define's were changed to reflect the new lowercase alias's.

Pull the fixed code here

Upvotes: 5

timDunham
timDunham

Reputation: 3318

Even though Backbone 0.5.3 registers itself as an AMD module, it doesn't return anything. (Same thing for underscore) If you change your line:

function($, _, Backbone){

To

function($){

It will work. For a more requirejs-ish solution, create a module for backbone that looks like:

define(
[
    'order!libraries/underscore',
    'order!libraries/backbone.0.5.3'
],
function () {
    return Backbone;
}
);

--UPDATE-- additional info

<head>
<title>Index2</title>
<script src="../../scripts/libraries/require.js" type="text/javascript"></script>
<script type="text/javascript"">
require({
baseUrl: 'scripts'
}, [
'order!libraries/jquery',
'order!libraries/underscore',
'order!libraries/backbone.0.5.3'
], function ($) {
console.log(Backbone);
});
</script>
</head> 

Upvotes: 1

Related Questions