Reputation: 1103
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
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