jbarreiros
jbarreiros

Reputation: 1103

Passing app object in requirejs + marionette application

Working with Marionette/Backbone and having trouble passing the App object in order to trigger a custom event.

Specifically, requirejs is throwing the following: "Error: Module name "app" has not been loaded yet for context: _".

Edit: The offending code is "var App = require('app');" within appController.js.

From what I've read, that message refers to a circular reference or the script not being loaded yet. How should I structure my code to avoid this?

Note 1: At the moment, I'm not using r.js. I do have a grunt build process, but haven't had a chance to set up r.js. Only mentioning it in case that would alleviate my issue.

Note 2: I'm not using Marionette's stock module because I wanted to learn requirejs.

Thanks in advance.

//config.js
require.config({
   paths: {
       jquery: '../jquery',
       bootstrap: '../bootstrap',
       underscore: '../lodash',
       backbone: '../backbone',
       'backbone.babysitter': '../backbone.babysitter',
       'backbone.wreqr': '../backbone.wreqr',
       marionette: '../backbone.marionette',
       text: '../text'
   },
   enforceDefine: true,
   shim: {
       'bootstrap': {
           deps: ['jquery'],
           exports: '$'
       },
   }
});
define(
    ['app', 'jquery', 'underscore', 'backbone', 'marionette', 'bootstrap'],
    function(App, $, _, Backbone, Marionette) {
        App.start();
    }
);

//app.js
define(function(require) {
    var Marionette = require('marionette'),
        // and AppRouter, AppController
    var app = new Marionette.Application();
    app.addInitializer(function() {
        var router = new AppRouter({
            controller: AppController
        });
    });
    app.on('start', function() {
        Backbone.history.start();
    });
    app.vent.on('custom:event', function(a) {
        console.log('caught custom:event, received: ' + a);
    });
    return app;
});

// appRouter.js
define(function(require) {
    var Marionette = require('marionette');
    return Marionette.AppRouter.extend({
        appRouter: {
            '': 'main'
        }
    });
});

//appController.js
define(function(require) {
    return {
        main: function() {
            var App = require('app');
            App.vent.trigger('custom:event', ['test']);
        }
    }
});

Update:

Of course after posting this question, I find a possible solution. If I adjust appController.js to the following, it works without issue. Still, the solution doesn't feel right. Would I have to duplicate it for every route?

//appController.js (version 2)
define(function(require) {
    return {
        main: function() {
            require(['app'], function(app) {
                app.vent.trigger('custom:event', ['test']);
            });
        }
    }
});

Update 2

If anyone is curious, this is how I got it working with Backbone.Wreqr (thank you @arisalexis). Only showing files changed from code above.

//app.js
define(function(require) {
    var Marionette = require('marionette'),
        Wreqr = require('backbone.wreqr'),
        // and AppRouter, AppController
    var app = new Marionette.Application();  
    app.addInitializer(function() {
        var router = new AppRouter({
            controller: AppController
        });
    });
    app.on('start', function() {
        Backbone.history.start();
    });
    // Get hook to global channel and listen for events!
    var channel = Wreqr.radio.channel('global');
    channel.vent.on('custom:event', function(a) {
        console.log('caught custom:event, received: ' + a);
    });
    return app;
});

//appController.js
define(function(require) {
    var Wreqr = require('backbone.wreqr');
    var channel = Wreqr.radio.channel('global');
    return {
        main: function() {
            channel.vent.trigger('custom:event', 'test');
        }
    }
});

Note, in general, the router's controller should not have any logic in it. The code presented in this question is a proof of concept.

Upvotes: 0

Views: 851

Answers (1)

arisalexis
arisalexis

Reputation: 2210

I had the same problem and could not solve it, luckily because it will be deprecated in version 3.

From the docs:

To access this application channel from other objects within your app you are encouraged to get a handle of the systems through the Wreqr API instead of the Application instance itself.

var globalCh = Backbone.Wreqr.radio.channel('global');
globalCh.vent;

use this or take a look at https://github.com/marionettejs/backbone.radio

Upvotes: 2

Related Questions