require js + backbone + marionette: Cannot read property 'Marionette' of undefined - backbone.js

I just started off learning backbone and want to manage my dependencies using require js.
My code is as follows:
main.js:
//Require.js
require.config({
paths : {
jQuery : '//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min',
jQueryUI : '//ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min',
lodash : 'libs/lodash/lodash',
backbone : 'libs/backbone/backbone',
marionette : 'libs/marionette/marionette'
},
shim : {
backbone: {
deps : ['jQuery', 'lodash'],
exports : 'backbone'
},
marionette: {
deps : ['backbone'],
exports : 'marionette'
}
}
});
require(['initialize'], function(initializer){
alert("initialized");
});
initialize.js:
define(['backbone', 'marionette'], function(Backbone, Marionette){
var appZwoop = new Backbone.Marionette.Application();
var options = {
};
//Initialize functions
appZwoop.addInitializer(function(options){
});
//Application events
appZwoop.on("initialize:before", function(options){
});
appZwoop.on("initialize:after", function(options){
});
//Start the application
appZwoop.start(options);
appZwoop.addRegions({
mainRegion : "#mainRegion",
headerRegion: "#headerRegion"
});
return appZwoop;
}
The browser console throws me the error:
Uncaught TypeError: Cannot read property 'Marionette' of undefined
What am I doing wrong ... ?

Change you Backbone shim to capitalize Backbone in the exports:
backbone: {
deps : ['jQuery', 'lodash'],
exports : 'Backbone'
},
because Backbone defines itself as Backbone and not backbone. There may be a problem elsewhere but you definitely have to do this.

Related

backbone.js: Right-hand side of 'instanceof' is not an object

I'm newer with jquery and backbone, hope someone could help me with this error. I have a web application that, sometimes, throws this error in the console
require.js:900 TypeError: Right-hand side of 'instanceof' is not an object
at child.setElement (backbone.js?__nc__=1527837925799:1040)
at child._ensureElement (backbone.js?__nc__=1527837925799:1102)
at child.Backbone.View (backbone.js?__nc__=1527837925799:990)
at child [as constructor] (backbone.js?__nc__=1527837925799:1545)
at new child (backbone.js?__nc__=1527837925799:1545)
at child.initialize (application.js?__nc__=1527837925799:357)
at child.Inditex.Application (backbone-inditex-1.2.0.js?__nc__=1527837925799:27)
at new child (backbone.js?__nc__=1527837925799:1545)
at createApp (main.js:201)
at Object.execCb (require.js:1690)
If this error happens, with a reload of the webpage is fixed (sometimes with 3 or 4 times) but I can't know why this happens.
I have found the line where this error is thrown. In backbone.js file, the method setElement
setElement: function(element, delegate) {
debugger;
if (this.$el) this.undelegateEvents();
this.$el = element instanceof Backbone.$ ? element : Backbone.$(element);
this.el = this.$el[0];
if (delegate !== false) this.delegateEvents();
return this;
},
sometimes, Backbone.$ is not an object and is when the error hapens.
¿Any idea for resolving this error? I'm using backbone.js 1.1.0
Thanks in advance
In my case, I could fix it change my main.js. The error was that, in some cases backbone was loaded before jquery were loaded. My main.js was like this
shim : {
'underscore' : {
exports: '_'
},
'backbone' : {
deps : ['underscore'],
exports: 'Backbone'
}
I had to add a deps in backbone for jquery, like this
shim : {
'underscore' : {
exports: '_'
},
'backbone' : {
deps : ['jquery','underscore'],
exports: 'Backbone'
}
The main reason of this problem is backbone.js loaded before jQuery, so what you need to do is just make sure that jQuery loads before backbone.js.

How can I use Marionette in my typescript project with require.js

I'm having some error as below;
Uncaught ReferenceError: Marionette is not defined
I am using the following files(main.ts->config, app.ts-> first class of the app) with using the grunt watch (typescript compile with --module amd). My question is refer to my error problem, How can I import Marionette (modules/marionette.d.ts) so that I could use Marionette.Application(); and configure my application?
main.ts;
// Require JS all the things
/// <reference path="modules/require.d.ts" />
/// <reference path="modules/marionette.d.ts" />
require.config({
basePath: 'assets/js',
paths : {
backbone : 'vendor/backbone',
underscore : 'vendor/underscore',
jquery : 'vendor/jquery',
marionette : 'vendor/backbone.marionette',
debug : 'vendor/ba-debug',
handlebars: 'vendor/handlebars'
},
shim : {
jquery : {
exports : 'jQuery'
},
underscore : {
exports : '_'
},
backbone : {
deps : ['jquery', 'underscore'],
exports : 'Backbone'
},
marionette : {
deps : ['jquery', 'underscore', 'backbone'],
exports : 'Marionette'
},
handlebars: {
exports:'Handlebars'
},
debug: {
exports: 'debug'
}
}
});
// initalise the app
// load AMD module app.ts (compiled to app.js) , tsc --module AMD main.ts
// and include shims $, _, Backbone
require(['backbone', 'app','routers/router','routers/controller', 'debug', 'jquery','underscore'], (Backbone, App, CustomRouter, AppController, debug, $, _ ) => {
debug.log('starting app');
App.on('initialize:after', function(options) {
if (Backbone.history) {
Backbone.history.start();
}
});
var router = new CustomRouter({
controller : new AppController()
});
App.start();
});
app.ts;
/// <reference path="modules/marionette.d.ts" />
var app:any = new Marionette.Application();
app.addRegions({
header : '#Header',
// main : CustomRegion.extend({el: '#main'})
main : '#Main'
});
app.addInitializer(function() {
});
Thanks
You need to tell requireJS to load marionette before it starts running app.js.
This is done using amd-dependency:
/// <amd-dependency path="marionette"/>
You can see a sample here : https://github.com/basarat/typescript-amd/blob/master/app/scripts/app.ts
Along with the video tutorial: http://www.youtube.com/watch?v=4AGQpv0MKsA
I'm using this as a reference and it works perfectly Structuring Backbone with RequireJS and Marionette . Hope this help you to solve your issue! :)

How do I correctly set up a Marionette EventAggregator as a Require.js module

I'm trying to setup a vent/EventAggregator as a separate Require.js module. I am using Marionette 1.0.2 (which I believe has a different implementation than legacy versions pre 1.0.0) with wreqr included: this code is from backbone.marionette.js:-
// Event Aggregator
// ----------------
// A pub-sub object that can be used to decouple various parts
// of an application through event-driven architecture.
Wreqr.EventAggregator = (function(Backbone, _){
"use strict";
var EA = function(){};
// Copy the `extend` function used by Backbone's classes
EA.extend = Backbone.Model.extend;
// Copy the basic Backbone.Events on to the event aggregator
_.extend(EA.prototype, Backbone.Events);
return EA;
})(Backbone, _);
When I set up my vent.js module what should it be? Something like this:-
define(['marionette'],function(Marionette){
return new Marionette.EventAggregator();
})
Also in my require config should I explicitly be including backbone.wreqr.js or not? Or should just the marionette file (see snippet from above) be sufficient?
For reference here is my app.js:-
require.config({
paths : {
backbone : 'lib/backbone',
underscore : 'lib/underscore',
jquery : 'lib/jquery',
marionette : 'lib/backbone.marionette',
'backbone.wreqr' : 'lib/backbone.wreqr',
text : 'lib/text',
templates : '../templates'
},
shim : {
jquery : {
exports : 'jQuery'
},
underscore : {
exports : '_'
},
backbone : {
deps : ['jquery', 'underscore'],
exports : 'Backbone'
},
marionette : {
deps : ['jquery', 'underscore', 'backbone'],
exports : 'Marionette'
},
'backbone.wreqr' : {
deps : ['backbone', 'marionette', 'underscore'],
exports : 'Wreqr'
}
}
})
require(
["jquery",
"underscore",
"backbone",
"marionette",
"backbone.wreqr",
"shell/shellapp"
],
function($, _, Backbone, Marionette, Wreqr, ShellApp) {
$(function() {
//new ShellApp();
var shell = ShellApp;
shell.start();
trace("shell: "+shell);
});
}
);
All help much appreciated!
Much thanks,
Sam
_______**** UPDATE
Thanks to Paul I figured out how to get my vent.js working. FYI I did NOT need to import the wreqr file seperately in the config. Here is the vent.js code:-
define(['backbone', 'marionette'],function(Backbone, Marionette){
return new Backbone.Wreqr.EventAggregator();
});
This works for me.
require.config({
paths: {
backbone: 'http://backbonejs.org/backbone',
underscore: 'http://underscorejs.org/underscore',
jquery: 'http://code.jquery.com/jquery-1.9.1',
marionette: 'http://marionettejs.com/downloads/backbone.marionette'
},
shim: {
jquery: {
exports: 'jQuery'
},
underscore: {
exports: '_'
},
backbone: {
deps: ['jquery', 'underscore'],
exports: 'Backbone'
},
marionette: {
deps: ['jquery', 'underscore', 'backbone'],
exports: 'Marionette'
}
}
});
require(["backbone", "marionette"], function (Backbone, Marionette) {
console.log(Backbone.Wreqr.EventAggregator);
var ea = new Backbone.Wreqr.EventAggregator();
console.log(ea);
});

backbone.marionette with handlebars throwing exceptions trying to load my template

here is the error thrown to my console
Uncaught TypeError: Object has no method 'chain' hbs.js:282
getExternalDeps hbs.js:282
(anonymous function) hbs.js:306
xhr.onreadystatechange hbs.js:73
Uncaught Error: Load timeout for modules: hbs!templates/reset_unnormalized2,hbs!templates/pages/login_unnormalized3,hbs!templates/reset,hbs!templates/pages/login
http://requirejs.org/docs/errors.html#timeout require.js:160
i'm using the handlebars-require-plugin and i've even tried adding "hbs" to my require shim but the result is the same.
here is my marionette view code:
define([
"bootstrap", // bootstrap does not export anything, so no arg sent to our function
"marionette",
"session", "events",
"hbs!templates/pages/login"
], function( Marionette, Session, Events, LoginTemplate ){
return Marionette.View.extend({
template : {
type : "handlebars",
template : LoginTemplate
}
});
});
i have no idea what's going on here and every search i've pulled up has yielded no useful results.
what's happening? why is this happening? please help.
Could be that you have your args to your callback incorrectly defined? If a value does not define anything (such as bootstrap) then make it last. Right now your Marionette arg contains the undefined value of bootstrap, Session now holds Marionette etc.
define([
"marionette",
"session", "events",
"hbs!templates/pages/login",
"bootstrap", // bootstrap does not export anything, so no arg sent to our function
], function( Marionette, Session, Events, LoginTemplate ){
return Marionette.View.extend({
template : {
type : "handlebars",
template : LoginTemplate
}
});
});
i figured it out.
it turns out my problem was not related to the hbs plugin as it was with using it, handlebars, and json2 with requirejs.
the first problem, as described above, was solved by switching out the lodash library with underscore. i was under the impression that these two were interchangeable, but apparently that is NOT the case.
then i was getting errors that "stringify" is not a function on the object null which led me to find that JSON was not defined inside hbs.
i had to go back to my require.config({ shim:{} }) and define json2 with an export of JSON
now i am not getting errors from hbs but i have to figure out why my view is not displaying.
here is my config code, should anyone else be interested.
require.config({
// paths to required javascript files
paths : {
bootstrap : "../assets/js/bootstrap.min",
jquery : "../assets/js/jquery.min",
json2 : "../assets/js/json2",
underscore : "../assets/js/underscore.min",
backbone : "../assets/js/backbone.min",
marionette : "../assets/js/backbone.marionette.min",
hbs : "../assets/js/hbs",
handlebars : "../assets/js/handlebars",
i18nprecompile : "../assets/js/hbs/i18nprecompile"
},
// "shim" will allows us to load in deps synchronously so that we do not
// run into a situation where dependencies are not available
shim : {
json2 : { exports : "JSON" },
jquery : { exports : "jQuery" },
underscore : { exports : "_" },
backbone : {
deps : ["jquery", "underscore", "json2"],
exports : "Backbone"
},
marionette : {
deps : ["jquery", "underscore", "json2", "backbone"],
exports : "Marionette"
},
hbs : {
deps : ["jquery", "underscore", "json2", "i18nprecompile", "handlebars"],
exports : "hbs"
},
bootstrap : { deps : ["jquery"] }
}
});

Requirejs2: How to handle own files?

I have configured requirejs to load the core libs (jquery, underscore, backbone).
Now I would like to add my backbone models, controllers, views, etc to be loaded asyncronly
I found a lots of tutorials to this topic and lots of "ready" boilerplates unfortunatly I mentioned that most approaches are depreceated or rather complicated (even there are better approaches).
One example is how I configured requirejs for the main libs:
https://stackoverflow.com/a/10914666/1309847
So how do I load Backbone Views, Models, Collections, Routers, Controllers and Templates with a simple and valid Requirejs configuration?
I followed youre advice but get some strange error
main.js
require.config({
paths: {
jquery: 'vendors/jquery/jquery',
underscore: 'vendors/underscore/underscore',
backbone: 'vendors/backbone/backbone'
},
shim: {
underscore: {
exports: '_'
},
backbone: {
deps: ['underscore', 'jquery'],
exports: 'Backbone'
}
}
});
require(['app'], function(app){
});
app.js
define(['jquery', 'underscore', 'backbone'], function($, _, Backbone){
var Message = new Backbone.Model.extend({
//idAttribute: '_id',
//defaults: { body: '' }
//url: function(){ return this.id ? '/messages/' + this.id : '/messages'; }
});
var newMessage = new Message({ body: 'hi' });
newMessage.save();
});
The error occours in app.js:
Uncaught TypeError: Object [object Object] has no method 'apply'
When I comment the new Backbone.Model.extend part I don't get any error anymore.
in my experience, the best way to bootstrap your application is by creating a Backbone.Router. So you can associate urls with your application functionality.
If you are using RequireJS+Backbone, you probably have a main.js where RequireJS is configured (paths, shims, etc). The first call to "require" is used to load a initial script in order to bootstrap the whole app.
For example:
/**
* main.js - RequireJS bootstrap
*/
require.config({
paths: {
//your paths
},
shim: {
//your shims
}
});
require(
[
'app' //app.js is at the same directory as main.js
],
function(app) {
app.init();
}
);
then in app.js you can create a new Router instance, or you can just start creating Views and Models.
For further reference: http://addyosmani.github.com/backbone-fundamentals/
So as I have now understood right: You have to wrap a requirejs function around youre own custom js file.
The function is called define. The first parameter is an array of the dependencies which you have defined in the main.js file or a relative path to another custom js from you.
The second parameter is the callback which holds the original file. Important is that you return the object, function, array or variable which you want to share.
The whole thing looks like this:
define(
['underscore', 'backbone'], // the dependencies (either relative paths or shortcuts defined in main.js
function(_, Backbone){ // the return statement of the deps mapped to a var
var MessageModel = Backbone.Model.extend({ // the original code, file
defaults: { body: '' },
initialize: function(){}
});
return MessageModel; // the return statement, sharing the "final result", sometimes you return the initialize parameter
});
The same for a collection wrapping the models:
define(
['jquery', 'underscore', 'backbone', 'models/message_model'], // deps and the last one is the relative path
function($, _, Backbone,MessageModel){ // same as above explained
var MessageCollection = Backbone.Collection.extend({
model: MessageModel,
initialize: function(){}
});
return MessageCollection;
});
I now only have to figure out how I can bootstrap to whole application. But I think I need more knowledge of backbone to do this :)

Resources