Backbone Marionette: Marionette.Application causing Require.js module load error, “'Error: Module name 'App' has not been loaded yet for context: _”

Question!

I'm trying to include the App instance to use it's event aggregator as shown here

I get an error when I include the instance in a view.

Kicking things off in the Requirejs config file, from App.Bootloader.js:

require(['App'], function (App){
      App.start();
      });

from App.js:

define(function (require){

  //...requisite includes $, _, Backbone, Marionette ...

var Layout = require('Layout');

  var App = new Marionette.Application();

        App.addRegions({
            main: '#view_content'
        });

        App.addInitializer(function (){

                App.main.show(new Layout());
                //... adding router etc ...    

                Backbone.Marionette.TemplateCache.loadTemplate = function (template, callback){
                   callback.call(this, Handlebars.compile(template));
                };
                Backbone.history.start();

        });

    return App;
});

From Layout.js:

define(function(require){
   var View = require('folder/folder/View');
   //template contains #sub div
   var template = require('text!template.html');

   return Marionette.Layout.extend({
      template: template,
      regions: {
         sub: '#sub'
      },
      initialize: function(){
         //wait till template is rendered in dom
         _.defer(function(region){
             region.sub.show(new View());
          }, this)
      }

   });

});

From /folder/folder/View.js:

define(function (require){

      //...requisite includes $, _, Backbone, Marionette ...

     var App = require('App');
     return Marionette.ItemView.extend({});
});

Where I get the error "'Error: Module name 'App' has not been loaded yet for context: _"

Any ideas? Lemme know if you need more information.



Answers

user1248256 is correct. I had the same problem. My App needed a controller and my Controller needed App.

By passing in the controller (view for your code) as part of options I don't have to add it to the require.js definition.

//data-main:
define(function(require) {
    var   $                 = require("jquery"),
        _                   = require("underscore"),
        App                 = require("app/App"),
        PublicRouter        = require("routers/DesktopRouter"),
        PublicController    = require("routers/publicController");

    var options = {
        publicController  :   PublicController,
        publicRouter      :   PublicRouter

    }

    App.start(options);
});

Now in App I don't have to "require" the PublicController

//App:
define(['jquery', 'backbone', 'marionette', 'underscore'],
function ($, Backbone, Marionette, _) {
    var App = new Marionette.Application();
    ...snip...
        console.log("Creating Routers");
        App.Routers = {};
        // Connect controllers to its router via options
        // init router's router/controller
        App.Routers.publicRouter = new options.publicRouter.Router({
            controller: options.publicController
        });
    });

Hope that helps.

Andrew



I generally think it's bad practice to use the app's EventAggregator when using requireJS, if for no other reason than it's really easy to wind up with a circular reference.

Just define a separate EventAggregator module that can be required by App, View, and Layout, then add it to the dependencies of any module that needs it.



This video can help you solving your question :)
By: admin