Search code examples
knockout.jsdurandal

Durandal gives "Cannot read property 'nodeType' of null" error


Been playing with Durandal 2.1.0, but cannot seem to get an example up an running. When I run it in Chrome I get the error "Cannot read property 'nodeType' of null".

Folder structure is: -viewmodels

|-vm1.js

-Scripts

|-durandal...

-views

|-vm1.html

-Index.html

index.html

<html>
<head>
    <title></title>
    <script src="Scripts/knockout-3.1.0.js"></script>
    <script src="Scripts/jquery-1.9.1.js"></script>
</head>
<body>
<script src="Scripts/require.js" data-main="Scripts\main"></script>
</body>
</html>

main.js

requirejs.config({
paths: {
    'text': 'Scripts/text',
    'durandal': 'Scripts/durandal',
    'plugins': 'Scripts/durandal/plugins',
    'viewLocator': 'durandal/viewLocator',
}
});

define('jquery', function () { return jQuery; });
define('knockout', ko);

define(function (require) {
    var system = require('durandal/system'),
        app = require('durandal/app'),
        router = require('plugins/router');

    system.debug(true);

    app.start().then(function () {
    app.setRoot('viewmodels/vm1');
});
});

vm1.js:

define(['plugins/router'], function (router) {
    return {
        router: router,
        activate: function () {
            //This line never fires
            alert();
        }
    }
});

PS: Installed with nuget. Assume any JS errors are typos, the script itself is ok. I have tried all manner of things moving the order of script loads around, using viewLocator to define the path manually. Seems to correspond perfectly to the examples I've seen on Durandal's site.

Any help appreciated.


Solution

  • Unless you're specifying paths directly, or using a custom viewLocator, you need to place your views directory and your viewmodels directory on the same level. In other words, they need to be siblings in the tree.

    Take a look at our main entry point in main.js. I have removed the irrelevant bits:

    function (system, app, viewLocator, bindings, extenders, validations) {
        //>>excludeStart("build", true);
        system.debug(true);
        //>>excludeEnd("build");        
    
        //Initialize KnockoutJS customizations
        bindings.init();
        extenders.init();        
    
        app.title = 'Some Application';
    
        app.configurePlugins({
            router: true,
            dialog: true,
            widget: true
        });
    
        app.start().then(function() {
            //Replace 'viewmodels' in the moduleId with 'views' to locate the view.
            //Look for partial views in a 'views' folder in the root.
            viewLocator.useConvention();
    
            //Show the app by setting the root view model for our application with a transition.
            app.setRoot('viewmodels/shell');
        });
    });
    

    I don't see where you call viewLocator.useConvention(), or otherwise customize the viewLocator.

    Also, where's your App directory? We have the following (among many other directories):

    App

    views

    viewmodels

    App is at the top level of our Web project on the server.