Creating a Module

####

Key Points

A Simple Example

To create a module, start by creating a new .js file. In this file, call define and pass it a function which will be used to build up your module. The return value of the function is what will be imported by other modules when they call require. Here's a simple example of two modules, one of which depends on the other:

backend.js

define(function(require){
  return {
    getCustomers:function(){
      //do some ajax and return a promise
    }
  };
});

customerList.js

define(function(require){
  var backend = require('backend');

  return {
    customers:ko.observableArray([]),
    activate:function(){
      var that = this;
      return backend.getCustomers().then(function(results){
        that.customers(results);
      });
    }
  };
});

As you can see here, both modules declare themselves by calling define. The customerList module also indicates that it has a dependency on backend by calling require and passing it the path to that module. The value assigned to the backend variable is the same object instance that was returned from the backend module.

Note: Module paths can be relative to the module which is calling require, or they can be absolute, based on the baseUrl of your app. Unless otherwise configured, the baseUrl is wherever your main.js resides.

Module Values

In the above example, both modules returned an object instance. This results in what would commonly be called a "singleton" object, since the same object instance is obtained by all who require it. You are not limited to this pattern, however. Another common module usage pattern is to return a constructor function from the module. This sets up an organization which is common to many other languages where you have one "class" per file. This allows dependent modules to create instances on demand. Here's a modified version of the above sample which demonstrates that:

backend.js

define(function(require){
  var backend = function(username, password){
    this.username = username;
    this.password = password;
  };

  backend.prototype.getCustomers = function(){
    //do some ajax and return a promise
  };

  return backend;
});

customerList.js

define(function(require){
  var Backend = require('backend');

  return {
    customers:ko.observableArray([]),
    activate:function(){
      var that = this;
      var service = new Backend('username', 'password');

      return service.getCustomers().then(function(results){
        that.customers(results);
      });
    }
  };
});

As you can see customerList depends on backend and uses the new modifier to create instances of it.

Important!

A module's define is only exeucted once, at the time the module is first required. As a result, if you return an object instance, you have created a singleton which will stay in memory for the lifetime of your application. If this is not desired, return a constructor function to retain greater control of the lifetime of your objects by allowing consumers to create/release them as needed.

Module Ids

Every module in your application has an Id. This Id is derived from its path, relative to your application's baseUrl. Unless otherwise configured, your baseUrl is the same as the location of your main.js file. As part of the module definition process, Durandal assigns every module its Id. This is stored in the semi-private field called __moduleId__. Should you need to inspect the Id of a module, it is better to use the system module's getModuleId(object) function than to access this field as the underlying storage mechanism may change in future versions.