Simple Dojo Example – require, declare (class), and modules

I’ve been exploring the Dojo Toolkit this weekend after looking at some examples that Cesium (Sandcastle example) ships with.  There are many good examples and tutorials on the Dojo website to get yourself familiar with Dojo and up to speed.  Dojo has been around for quite some time, but it’s evolved – at the time of this writing I’m using version 1.9.

I’m a fan of RequireJs  – so to see that Dojo is built upon the same AMD concept as RequireJs is quite intriguing to me!  RequireJs allows for better structured JavaScript using concepts such as ‘dependency injection’ that many OO programmers are aware of.

Let’s jump into an example of how to use Dojo!  My example is built on two dojo tutorials (Introduction to AMD Modules and Classy Javascript).  To keep things simple and interesting, I’m using NodeJS to run this sample.  (All the source code for this post can be pulled down from my github repository).

Just to get this out of the way – let’s get our environment setup.  If you haven’t already, make sure you have NodeJs installed.  Keep in mind, NodeJs isn’t required to actually run this code, you can use any web server.   Create a new directory – ie. ‘modules’ and then enter the command ‘npm install connect’.  Node Connect is a simple and quick way to fire up a web server.  You should now see a ‘node_modules’ directory inside our modules folder.  The next step is to create our server – created a server.js file in the modules folder.  The code should look like this:

var connect = require('connect');
connect.createServer(
        connect.static(__dirname)
        ).listen(8080);
console.log('server running on port 8080');

Node makes it quite easy to get up and running, so this should be enough for our web server!  Let’s move on to what we came here to do!

As mentioned above, you can get the source code from my github repo – but lets take a look at the project structure:

image

As you can see, I have a ‘app’ folder with two javascript files.  The index.html will contain the code to run our simple example.  Let’s take a look at our index.html file:

<html>
    <head>
        <link rel="stylesheet" href="style.css" media="screen">
        <script>
    dojoConfig = {
        async: true,
        packages:[{
            name:"app", location:"/app"
        }]
    };
</script>
        <script src="//ajax.googleapis.com/ajax/libs/dojo/1.9.0/dojo/dojo.js"></script>
        <script>
            require([
                    "app/counter", "app/logger"
                ], function(counter, Logger){
                var logger = new Logger();
                logger.log(counter.getValue());
                counter.increment();
                logger.log(counter.getValue());
                counter.decrement();
                logger.log(counter.getValue());
            });
        </script>
    </head>
    <body>
    </body>
</html>

As you can see, I’m supplying our main dojo.js file via CDN.  The next section here in the script tags is our application (normally I’d even have this code in a separate .js file – but for now this will suffice).  We wrap our code up in our ‘require’ statement.  The first part of this is an array of strings for each dependency our application has.  In this case, we have a dependency on ‘counter’ and ‘logger’ (we do not use ‘.js’ as this will make them non-AMD modules).  The function that follows matches our two dependencies and provides access to that code, ‘counter’ and ‘Logger’.  In this example we can see that one is a ‘static’ object whereas the other is an object we will create. As you can see, this helps keep our code rather clean, the rest of the code.

Let’s take a look at the ‘counter.js’ code first – as it’s the simplest to follow:

define(function(){
    var privateValue = 0;
    return {
        increment: function(){
            privateValue++;    
        },
        decrement: function(){
            privateValue--;
        },
        getValue: function(){
            return privateValue;
        }
    }
});

Dojo provides some good structure for us to create our modules.  In this case, we are wrapping our code in a ‘define’ function which tells Dojo this is a module and will be accessible from our application.   Dojo will handle loading and injecting this module into our main application. 

The second module this application uses is our ‘logger.js’ file.  This code takes a next step by wrapping our code in an object, aka class:

define(function(){
    var privateValue = 0;
    return {
        increment: function(){
            privateValue++;    
        },
        decrement: function(){
            privateValue--;
        },
        getValue: function(){
            return privateValue;
        }
    }
});

The define in this example has some additional dependencies.  All four of these dependencies comes from the dojo framework.  This really shows how modular dojo is and how easy it is to cleanly separate your apps concerns  (Initially when building this application, I had this code in the index.html, then refactored it out to keep the index.html code very clean!).

This code introduces a second concept – that of ‘declare’.  To understand and see how to use ‘declare’ – take a look at the Dojo ‘live docs’ definition.  This particular object will expose a ‘log’ function.  Other libraries try to mimic a ‘class’ definition (aka Typescript, Backbone, etc..) whereas I believe through Dojo’s ‘declare’ it’s more in line with how most people write javascript today.   Since we aren’t creating the object in this code nor returning an object literal, the ‘return declare’ will allow the caller to instantiate the object. 

The live docs link above to declare provides good documentation with several examples.  I appreciate the inheritance and mixin capabilities of declare.

This should wrap up this post – I hope to share more as I further explore using Dojo with Require.  If you have any questions or feedback please share!

(Just a side note: I’ve been using KnockoutJS on several applications and recommend taking a look at the DurandelJS framework that creates a RequireJS/AMD application structure around KnockoutJS – you can see the power of using RequireJs/AMD).

Advertisements

One thought on “Simple Dojo Example – require, declare (class), and modules

  1. Thanks for the example. At the time of this writing (Feb 2014), the two “define” snippets are identical – there is no additional dependency in the second one (last dark block). I am very new to dojo and maybe I am missing something obvious.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s