Skip to content

Using marionette with requirejs

kahwee edited this page Apr 29, 2013 · 18 revisions

Simple Usage

Using any AMD loader that supports AMD shim configuration (example RequireJS documentation), you can load the Marionette bundle and define the bundle's dependencies fairly easily.

This example shim configuration shims Marionette and Backbone and also provides export values for jQuery and underscore.

require.config({
  paths : {
    backbone : 'path/to/backbone',
    underscore : 'path/to/underscore',
    jquery : 'path/to/jquery',
    marionette : 'path/to/marionette'
  },
  shim : {
    jquery : {
      exports : 'jQuery'
    },
    underscore : {
      exports : '_'
    },
    backbone : {
      deps : ['jquery', 'underscore'],
      exports : 'Backbone'
    },
    marionette : {
      deps : ['jquery', 'underscore', 'backbone'],
      exports : 'Marionette'
    }
  }
})

Advanced usage

More advanced and traditional AMD users will want to manage their own dependencies as AMD modules and can do so with the Marionette core AMD build. This is a normal AMD module that defines its dependencies and requires you to supply paths to its components as AMD modules.

You will still need to shim Backbone as the official distribution is not an AMD module.

require.config({
  paths : {
    backbone : 'path/to/backbone',
    underscore : 'path/to/underscore',
    jquery : 'path/to/jquery',
    marionette : 'path/to/marionette',
    'backbone.wreqr' : 'path/to/backbone.wreqr',
    'backbone.eventbinder' : 'path/to/backbone.eventbinder',
    'backbone.babysitter' : 'path/to/backbone.babysitter'
  },
  shim : {
    jquery : {
      exports : 'jQuery'
    },
    underscore : {
      exports : '_'
    },
    backbone : {
      deps : ['jquery', 'underscore'],
      exports : 'Backbone'
    }
  }
})

Defining your application as a module

define( ["marionette"], function (Marionette) {

    // set up the app instance
    var MyApp = new Marionette.Application();

    // configuration, setting up regions, etc ...

    // export the app from this module
    return MyApp;
});

Avoiding Circular Dependencies

The primary cause for circular dependencies is being over-dependent on your application object for something like the event aggregator, YourApp.vent.

Assuming you are setting up and returning your application in its own AMD module as in the above example, you can't require your application in one of its dependencies without causing an circular dependency, e.g.

// MyApp.js 
define(['marionette','depA'],function(marionette, depA){
  var MyApp = new Marionette.Application();
  // do something with depA
  return MyApp;
})
// depA.js
define(['MyApp'],function(MyApp){
  // app will always be undefined because 
  // MyApp depends on depA which depends on MyApp.
  // MyApp can't be satisfied until depA is satisfied.
})

You can use the string-argument form of require in your dependent modules' methods in order to get the application during later execution.

// depA.js
define(function(){
  return {
    myMethod : function() {
      var MyApp = require('MyApp');
      // since depA can now be satisfied and returned, when
      // depA.myMethod() is called, it is free to retrieve MyApp
      // on its own.
    }
  }
})

Example with central vent

Requiring your application everywhere can be tedious and there are usually better solutions. If you find yourself doing this a lot for the vent, you are probably better off making a separate module to act as the central app vent. Making smaller modules with fewer dependencies is generally the solution for AMD problems surrounding circular dependencies.

Vent module definition

with marionette version < 1.0.0-rc4

// vent.js
define(['marionette'],function(marionette){
  return new Marionette.EventAggregator();
})

with marionette version >= 1.0.0-rc4

// vent.js
define(['backbone.wreqr'],function(Wreqr){
  return new Wreqr.EventAggregator();
})

Usage

Now you have a 'global' vent module that doesn't explicitly depend on your application and can be depended on anywhere.

define(['vent'], function(vent) {
  vent.on('eventName', function(){});
  vent.trigger('eventName');
})

Loading templates as dependencies

You can use any of the template loader plugins that will manage your template dependencies as text files, automatically compile them and return them to your dependent modules.

Known template loader plugins :

Example usage with Underscore

Using ZeeAgency's plugin

define("marionette", "tpl!templates/myView.tpl",function(Marionette,myViewTemplate){
  var MyItemView = Marionette.ItemView.extend({
    template : myViewTemplate
  })

  // That's it! Marionette takes template functions as-is 
  // so there is nothing more that needs to be done.
  return MyItemView;
})
Clone this wiki locally