require dependencies (loading in a order to prevent errors) - backbone.js

I am using require in my app and on certain android devices and every now and again on the web I get an error like jQuery is not defined or Backbone not defined]
my index page is simple and has a link to my require
<script data-main="js/main" src="js/vendor/require/require.js"></script>
within here I setup all paths and the call the router as well as switching off the routing for JQM
require.config({
paths: {
jquery: 'vendor/jqm/jquery_1.7_min',
jqm: 'vendor/jqm/jquery.mobile-1.1.0',
underscore: 'vendor/underscore/underscore_amd',
backbone: 'vendor/backbone/backbone_amd',
text: 'vendor/require/text',
templates: '../templates',
views: '../views',
models: '../models'
}
});
define(['router','jqm-config'], function(app) {
});
then on my router page I define what is needed there..
define(['jquery', 'underscore', 'backbone','views/home/home',
'models/products/productCollection',
'views/products/productTypes',
'jqm'],
function($, _, Backbone,HomeView,ProductsType,ProductListView ) {
var AppRouter = Backbone.Router.extend({
//code here
});
$(document).ready(function () {
console.log('App Loaded');
app = new AppRouter();
Backbone.history.start();
});
return AppRouter;
});
how do i stop these errors occuring?

In your require.config you could add a shim section to define those dependencies:
require.config({
// The shim config allows us to configure dependencies for
// scripts that do not call define() to register a module
shim : {
'underscore' : {
exports : '_'
},
'backbone' : {
deps : [ 'underscore', 'jquery' ],
exports : 'Backbone'
},
'dataTables' : {
deps : [ 'jquery' ],
exports : 'dataTables'
}
},
paths : {
...

Related

Angular + requirejs Chrome error: Uncaught Error: [$injector:modulerr] Failed to instantiate module

after a lot of searching and no answers fit my particular error, here is what i got:
I have an application in angular using requirejs, the app works good in firefox, but for some reason in chrome is not loading correctly and throws an error: Uncaught Error: [$injector:modulerr] Failed to instantiate module Portfolio due to..
The only difference i can see in both browsers is the dependency load order, here is my code:
(function () {
require.config(
{
baseUrl: "protected/js",
paths : {
'jquery' : '../../assets/js/external-libs/jquery/jquery.min.2.1.1',
'jQueryUI' : '../../assets/js/external-libs/jquery/jquery-ui-1.11.2.min',
'async' : '../../assets/js/external-libs/requirejs-plugins/async',
'propertyParser' : '../../assets/js/external-libs/requirejs-plugins/propertyParser',
'text' : '../../assets/js/external-libs/requirejs-plugins/text',
'utils' : '../../assets/js/utils',
'bootstrap' : '../../assets/js/external-libs/bootstrap/bootstrap.min',
'ui-bootstrap' : '../../assets/js/external-libs/plugins/ui-bootstrap',
'underscore' : '../../assets/js/external-libs/underscore/underscore',
'plugins' : '../../assets/js/external-libs/plugins',
'angular' : '../../assets/js/external-libs/angular/angular.1.4.0-beta.4.min'
},
shim : {
'plugins' : {
deps : ['jquery'],
exports: 'plugins'
},
'jQueryUI': {
export: "$",
deps : [
'jquery',
'plugins/jquery.backstretch.min',
'plugins/jquery.easypiechart',
'plugins/jquery.flexslider.min',
'plugins/jquery.masonry.min',
'plugins/jquery.scrollto',
'plugins/jquery-plugins',
'plugins/modernizr.min'
]
},
'bootstrap': {
deps: ["jquery"]
},
'angular' : {
deps : ["jquery", "bootstrap"],
exports: 'angular'
}
}
}
);
define(
[
'require',
'jquery',
'utils',
'angular',
'directives/contentDirective',
'directives/navDirective'
], function (require, jQuery, utils, angular, contentDirective, navDirective) {
'use strict';
var app = angular.module('Portfolio', []);
app.run(['$rootScope', function ($rootScope) {
$rootScope.utils = utils;
$rootScope.settings = utils.storage('localSettings');
$rootScope.scrollSpyRefresh = function () {
setTimeout(function () {
$('body').scrollspy('refresh');
}, 1000);
};
}]);
app.factory(
"httpPost",
function () {
function transformRequest(data, getHeaders) {
var headers = getHeaders();
headers[ "Content-type" ] = "application/x-www-form-urlencoded; charset=utf-8";
return( serializeData(data) );
}
return( transformRequest );
function serializeData(data) {
if (!angular.isObject(data)) {
return( ( data == null ) ? "" : data.toString() );
}
var buffer = [];
for (var name in data) {
if (!data.hasOwnProperty(name)) {
continue;
}
var value = data[ name ];
buffer.push(
encodeURIComponent(name) +
"=" +
encodeURIComponent(( value == null ) ? "" : value)
);
}
var source = buffer
.join("&")
.replace(/%20/g, "+")
;
return( source );
}
}
);
app.directive('contentView', contentDirective);
app.directive('nav', navDirective);
return app;
}
);
})();
Load order:
In Firefox angular loads in 11 place and jquery loads first, in chrome angular loads 2 and jquery in 10 place

backbone.js Uncaught TypeError: Cannot read property 'View' of null

When I run my backbone app in NetBeans 7.3.1, the main page displays for a few seconds, maybe 5 or 6, then in NetBeans output I see the following...
Uncaught TypeError: Cannot read property 'View' of null (18:43:36:307 | error, javascript)
at (js/views/HomeView.js:6:28)
at d.execCb (js/libs/require/require.js:27:197)
at o (js/libs/require/require.js:10:471)
at (js/libs/require/require.js:12:184)
at o (js/libs/require/require.js:12:75)
at (js/libs/require/require.js:14:1)
at o (js/libs/require/require.js:12:75)
at l (js/libs/require/require.js:12:336)
at g.finishLoad (js/text.js:10:192)
at g.load (js/text.js:10:354)
at window.undefined.window.navigator.window.document.c.onreadystatechange (js/text.js:7:30)
Uncaught TypeError: Cannot read property 'Model' of null (18:43:36:317 | error, javascript)
at (js/models/Member.js:6:26)
at d.execCb (js/libs/require/require.js:27:197)
at o (js/libs/require/require.js:10:471)
at x (js/libs/require/require.js:15:186)
at m (js/libs/require/require.js:15:207)
at g.completeLoad (js/libs/require/require.js:21:388)
at d.onScriptLoad (js/libs/require/require.js:27:490)
Uncaught Error: Load timeout for modules: text!templates/homeTemplate.html
http://requirejs.org/docs/errors.html#timeout (18:43:38:511 | error, javascript)
at N (js/libs/require/require.js:7:217)
at A (js/libs/require/require.js:16:230)
at (js/libs/require/require.js:16:394)
It looks like RequireJS is failing to load Backbone. Here is main.js...
// Filename: main.js
require.config({
shim: {
underscore: {
exports: '_'
},
backbone: {
deps: ['underscore', 'jquery'],
exports: 'Backbone'
}
},
paths: {
jquery: 'libs/jquery/jquery-min',
underscore: 'libs/underscore/underscore-min',
backbone: 'libs/backbone/backbone-min',
templates: '../templates'
}
});
require([
'app',
], function(App) {
App.initialize();
});
I'm totally spinning my wheels on this. Why is Require not loading Backbone?
#Sushanth--: Edited original post to include HomeView.js
Here is the HomeView.js...
define([
'jquery',
'underscore',
'backbone',
'text!templates/homeTemplate.html'
], function($, _, Backbone, homeTemplate) {
var HomeView = Backbone.View.extend({
el: $("#page"),
initialize: function() {
},
render: function() {
var compiledTemplate = _.template( homeTemplate, {} );
this.$el.html( compiledTemplate );
}
});
return HomeView;
});
#Sushanth--: I'm rendering from the router.js...
// Filename: /js/router.js
define([
'jquery',
'underscore',
'backbone',
'views/HomeView',
'views/MembersView'
], function($, _, Backbone, HomeView, MembersView) {
var AppRouter = Backbone.Router.extend({
routes: {
// Define some URL routes
'members': 'showMembers',
// Default
'*actions': 'defaultAction'
}
});
var initialize = function(){
//alert('router init');
var app_router = new AppRouter;
app_router.on('route:showMembers', function () {
// Like above, call render but know that this view has nested sub views which
// handle loading and displaying data from the GitHub API
var membersView = new MembersView();
});
app_router.on('route:defaultAction', function (actions) {
// We have no matching route, lets display the home page
var homeView = new HomeView();
homeView.render();
});
// Unlike the above, we don't call render on this view as it will handle
// the render call internally after it loads data. Further more we load it
// outside of an on-route function to have it loaded no matter which page is
// loaded initially.
//var footerView = new FooterView();
//alert('hello from router.js');
//Backbone.history.start({pushState: true, root: "/modular-backbone/"});
//Backbone.history.start({pushState: true});
Backbone.history.start();
};
return {
initialize: initialize
};
});
Added a test alert in main.js, app.initialize...
require(['app'], function(App) {
// THIS ALERT NEVER DISPLAYS!?!?!
alert('inside main.js before app.initialize');
App.initialize();
});
I replaced my Backbone and Underscore js files with the AMD versions and it started working.

Backbone is not defined

I'm using backbone.js with require.js. I tried one tutorial and this is my index.html :
<script src="app/script/libs/require/require.js" data-main="app/script/main" type="text/javascript"></script>
<script src="app/script/router.js" type="text/javascript"></script>
<script type='text/javascript'>
$(document).ready(function()
{
var appRouter = new AppRouter(); // Router initialization
Backbone.history.start(); // Backbone start
});
</script>
And this is main.js :
require.config({
urlArgs: "bust=" + (new Date()).getTime(),
paths: {
jquery: 'libs/jquery/jquery',
underscore: 'libs/underscore/underscore',
backbone: 'libs/backbone/backbone'
}
});
require(["jquery", "underscore", "backbone"],
function ($, _, Backbone) {
console.log("Test output");
console.log("$: " + typeof $);
console.log("_: " + typeof _);
console.log("Backbone: " + typeof Backbone);
}
);
And this is my console:
ReferenceError: Backbone is not defined
[Break On This Error]
$(document).ready(function()
ReferenceError: $ is not defined
[Break On This Error]
$(document).ready(function()
Test output
$: function
_: function
Backbone: object
Require.js is working, but the backbone and jquery is undefined, I don't know what's wrong with them.
This is the structure of my file :
Any idea please. Thanks
You should also declare your libs in shim config
require.config({
urlArgs: "bust=" + (new Date()).getTime(),
paths: {
jquery: 'libs/jquery/jquery',
underscore: 'libs/underscore/underscore',
backbone: 'libs/backbone/backbone'
},
shim: {
'backbone': {
deps: ["underscore", "jquery"],
exports: "Backbone"
},
'underscore': {
exports: "_"
}
}
});
require(["jquery", "underscore", "backbone"],
function ($, _, Backbone) {
console.log("Test output");
console.log("$: " + typeof $);
console.log("_: " + typeof _);
console.log("Backbone: " + typeof Backbone);
}
);
With your setup you can use Backbone only if it was injected as a dependency in a requireJS module, it is not available in the global name space. Also requiring something that you need in most of every module like jquery, Backbone or underscore seems not the best idea. Just load them as script tag before your requireJS main file and everything is fine.
If you want to keep the shim solution you have to start your app inside a the main.js file
require.config({
urlArgs: "bust=" + (new Date()).getTime(),
paths: {
jquery: 'libs/jquery/jquery',
underscore: 'libs/underscore/underscore',
backbone: 'libs/backbone/backbone'
}
});
require(["jquery", "underscore", "backbone"],
function ($, _, Backbone) {
console.log("Test output");
console.log("$: " + typeof $);
console.log("_: " + typeof _);
console.log("Backbone: " + typeof Backbone);
$(document).ready(function() {
var appRouter = new AppRouter(); // Router initialization
Backbone.history.start(); // Backbone start
});
}
);

Require js not loading module

I have been staring at this for a while and can't seem to figure out why some AMDs aren't available after loading them as dependencies. I have a custom module called "models"; a bundle configured in my MVC project with the virtual path "/scripts/models.js". When I define it in require.config and as a dependency, it loads the file. I can see it was requested and found. No errors from require. However, when I try to reference it as the loaded dependency argument passed into my router, it's undefined (models.userModel).
Is there something I am doing wrong here? I don't see any circular dependencies and I have tried defining the models module by giving it a name. It is undefined regardless if I define it globally or request the module by path in my router.js file.
app.js. Main config. (below)
require.config({
baseUrl: "/scripts/app",
paths: {
jquery: "../jquery",
underscore: "libs/underscore",
backbone: "libs/backbone",
kendo: "libs/kendo",
models: "../models"
},
// We shim Backbone since it doesn't declare an AMD module
shim: {
underscore: {
exports: "_"
},
backbone: {
deps: ["underscore", "jquery"],
exports: "Backbone"
}
},
});
require([
"jquery",
"backbone",
"kendo",
"models",
"router"
], function ($, backbone, kendo, models, router) {
alert("config-start");
});
user.js. Indcluded in the models.js bundle. (below)
define({
userModel : kendo.observable({
datasource: kendo.data.DataSource({
transport: {
read: {
url: "/api/usersettings",
dataType: "json",
type: "GET"
},
update: {
url: "/api/usersettings",
dataType: "json",
type: "PUT"
}
},
schema: {
model: {
id: "UserId"
}
},
parameterMap: function (options, operation) {
if (operation !== "read" && options.models) {
return {
models: kendo.stringify(options.models)
};
}
return options;
}
}),
save: function () {
this.data.sync();
},
})
});
router.js file (below)
define(["jquery",
"backbone",
"models"
], function ($, backbone, models) {
/**
* The Router class contains all the routes within the application -
* i.e. URLs and the actions that will be taken as a result.
*
* #type {Router}
*/
var Router = Backbone.Router.extend({
contentArea: $("#MainContent"),
routes: {
"user/usersettings/contact": "contact",
"user/usersettings/security": "security",
"user/usersettings/dashboard": "dashboard",
"user/usersettings/permissions": "permissions",
"user/usersettings/colors": "colors"
},
contact: function () {
var contactTemplate = kendo.template($("#usersettings-usercontact").html());
this.contentArea.empty();
this.contentArea.html(contactTemplate);
kendo.bind(this.contentArea, models.userModel); // models is undefined
},
security: function () {
},
dashboard: function () {
},
permissions: function () {
},
colors: function () {
}
});
// Create a router instance
var router = new Router();
//Begin routing
Backbone.history.start();
return router;
});
Maybe I am missing something obvious, but I have not been able to load "models" as an external dependency. It is undefined when referencing from router.js. On the "contact" function.
Define needs a function that will return a value, this value then will be injected when it was required in another module.
Source code comment:
/**
* The function that handles definitions of modules. Differs from
* require() in that a string for the module should be the first argument,
* and the function to execute after dependencies are loaded should
* return a value to define the module corresponding to the first argument's
* name.
*/
define(function(){
return {
userModel: ...
}
})

Backbone JS, Marionette and Require JS

I am trying to get to grips with Backbone and Require JS using marionette for some of its excellent features. However I am finding a few issues with the app being available to views:
main.js
require(['application'], function(app){
app.start();
});
application.js
define([
'marionette',
'router'
], function(marionette, Router){
"use strict";
var app = new marionette.Application();
app.addRegions({
header : 'header',
main : '#main'
});
app.addInitializer(function(){
this.router = new Router();
});
return app;
});
dashboard.js
define([
'application',
'underscore',
'backbone',
], function(app, _, Backbone) {
var DashboardView = Backbone.View.extend({
initialize: function() {
console.log(app);
$('a').click(function(e){
e.preventDefault();
app.router.navigate("claims", {
trigger: true
});
});
},
});
return DashboardView;
});
I am receiving undefined in the console log? Should the application be using requirejs modules instead?
EDIT: Update with require
require.config({
paths: {
'jquery' : '../vendors/jquery-1.8.2',
'underscore' : '../vendors/underscore',
'text' : '../vendors/text',
'json2' : '../vendors/json2',
'backbone' : '../vendors/backbone',
'marionette' : '../vendors/plugins/backbone.marionette',
'paginator' : '../vendors/plugins/backbone.paginator',
'relational' : '../vendors/plugins/backbone.relational',
'moment' : '../vendors/moment',
'bootstrap' : '../vendors/bootstrap',
'datepicker' : '../vendors/plugins/bootstrap.datepicker',
'templates' : 'templates/'
},
shim: {
backbone: {
deps: ['underscore', 'jquery'],
exports: 'Backbone'
},
marionette : {
exports : 'Backbone.Marionette',
deps : ['backbone']
},
paginator: {
deps: [
'backbone',
'underscore',
'jquery'
],
exports: 'Backbone.Paginator'
},
relational: ['backbone'],
underscore: {
'exports': '_'
},
bootstrap: {
deps: ['jquery'],
exports: "bootstrap"
},
datepicker: {
deps: ['jquery','bootstrap'],
exports: "datepicker"
},
moment: {
exports: 'moment'
}
}
});
require(['application'], function(app){
app.start();
});
router
define([
'views/claims/PaginatedList',
'views/dashboard/Dashboard'
], function(PaginatedClaimListView, DashboardView){
var Router = Backbone.Router.extend({
routes: {
"": "index",
"claims": "claims"
},
initialize: function(){
Backbone.history.start({
pushState: true,
root: '/app_dev.php/hera'
});
},
index: function(){
var dashboard = new DashboardView();
},
claims: function(){
var claimListView = new PaginatedClaimListView();
}
});
return Router;
});
I think I've figured it out, even if I'm not 100% sure why.
The problem lies in your Router definition. Putting there your views with a reference to Application makes the router start before app.start() is called in main.js. In fact if you put a console.log(app) in your main.js you'll notice that it gets called after the one in dashboard.js.
So here's how I've resolved it:
define(['backbone'], function(Backbone){
var Router = Backbone.Router.extend({
routes: {
"": "index",
"claims": "claims"
},
initialize: function(){
Backbone.history.start({
pushState: true,
root: '/app_dev.php/hera'
});
},
index: function(){
require(['views/dashboard/Dashboard'],function(DashboardView){
var dashboard = new DashboardView();
});
},
claims: function(){
require(['views/claims/PaginatedList'],function(PaginatedClaimListView){
var claimListView = new PaginatedClaimListView();
});
}
});
return Router;
});
I'm not sure if there's a better solution that keeps your views defined in your router, anyway this works and will make your router lighter, especially if your views grown in number...
I've found that usually whenever I have Require.js modules set to undefined when they shouldn't be, it's because of a circular dependency. For instance, let's say "vent" depended on "dashboard"; you'd have: vent needs dashboard needs application needs vent ...
When this happens Require's response is essentially just to just pick one of the files and make it work, but any of the other files involved in the circular dependency come in as undefined.
You can test this theory by removing imports to see if that fixes your undefined. Alternatively the Require folks have a tool you can download called xrayquire which assists in finding circular dependencies.
Do you have to access the router via app.router? Can you not just have dashboard require router on its own, and access it directly? As long as application has already executed (which it should have, at that point), then you don't need to access it via app. I think your problem is definitely a complicated circular dependency.

Resources