RequireJS - "No define call for" several angular related libs - javascript

I struggling with understanding why I'm seeing several "No define call for" when attempting to load my angular application. Well I know they are there because I'm using enforeDefine: true, but what is wrong with my code? What do I need to do to satisfy the enforceDefine?
Errors:
main.js
/*global require, requirejs */
'use strict';
requirejs.config({
enforceDefine: true,
paths: {
angular: ['//cdn.jsdelivr.net/webjars/org.webjars/angularjs/1.4.0/angular.min','../lib/angularjs/angular.min'],
'angular-messages': ['//cdn.jsdelivr.net/webjars/org.webjars/angularjs/1.4.0/angular-messages.min','../lib/angularjs/angular-messages.min'],
'angular-resource': ['//cdn.jsdelivr.net/webjars/org.webjars/angularjs/1.4.0/angular-resource.min','../lib/angularjs/angular-resource.min'],
'angular-ui-bootstrap': ['//cdn.jsdelivr.net/webjars/org.webjars/angular-ui-bootstrap/0.13.0/ui-bootstrap-tpls.min','../lib/angular-ui-bootstrap/ui-bootstrap-tpls.min'],
uiRouter: ['//cdn.jsdelivr.net/webjars/org.webjars/angular-ui-router/0.2.15/angular-ui-router.min','../lib/angular-ui-router/angular-ui-router.min'],
bootstrap: ['//cdn.jsdelivr.net/webjars/org.webjars/bootstrap/3.3.4/bootstrap.min','../lib/bootstrap/js/bootstrap.min'],
jquery: ['//cdn.jsdelivr.net/webjars/org.webjars/jquery/2.1.4/jquery.min','../lib/jquery/jquery.min'],
async: '../lib/requirejs-plugins/src/async'
},
shim: {
angular: {
exports : 'angular'
},
uiRouter: {
deps: ['angular']
},
'angular-ui-bootstrap': {
deps: ['angular']
},
'angular-resource': {
deps: ['angular']
},
'angular-messages': {
deps: ['angular']
},
bootstrap: {
deps: ['jquery'],
exports: 'jQuery.fn.popover'
}
},
deps: ['app']
});
app.js
/*global require, requirejs */
'use strict';
define(['angular',
'./controllers',
'./directives',
'./filters',
'./services',
'bootstrap',
'jquery',
'uiRouter',
'angular-ui-bootstrap',
'angular-messages',
'angular-resource',
'async',
'./gmaps'
],
function(angular, controllers) {
// Declare app level module which depends on filters, and services
angular.module('myApp', ['myApp.filters', 'myApp.services', 'myApp.directives', 'ui.router', 'ngMessages','ngResource','ui.bootstrap']).
config(['$stateProvider','$urlRouterProvider','$httpProvider', function($stateProvider, $urlRouterProvider, $httpProvider) {
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
$urlRouterProvider.otherwise('/home');
$stateProvider
// HOME STATES AND NESTED VIEWS ========================================
.state('home', {
url: '/home',
.... several routes here that I hid
});
}]).controller('RouteCtrl', ['$scope','$state', function($scope, $state) {
$scope.$state = $state;
}]);
angular.bootstrap(document, ['myApp']);
});

From this (emphasis mine):
enforceDefine: If set to true, an error will be thrown if a script loads that does not call define() or have a shim exports string value that can be checked.
So the script loaded must either comply with AMD (Angular doesn't) or define an exports in its shim configuration.
Since main is yours, just make it a proper AMD module. The "problem" is that the other scripts (uiRouter, angular-ui-bootstrap, angular-resource, angular-messages) do not actually export anything. My suggestion is just re-export angular (or any other global, e.g. document, but angular seems more relevant) so that you satisfy RequireJS:
requirejs.config({
...
'angular-resource': {
deps: ['angular'],
exports: 'angular'
}, // and so on...
...
});
This is a bypass, but I do not think there is any other way, if you insist on using enforceDefine.

You might need to change the require inside the script you specify as being data-main to be a define instead. There has been a issue on GitHub noted that sounds similar to what you are running into.
The library author suggests that if you use the enforceDefine flag then your data-main module should also use a define.

Related

Require JS, Loading Libraries through CDN fails

I have read the answer to this question require js loading scripts from cdn fail. But in my case it does not help. I have a require JS setup and I want to use CDN to load my libraries.
The Require JS documentation says below is the right way to load libs from CDN with a fallback to local files.
requirejs.config({
//To get timely, correct error triggers in IE, force a define/shim exports check.
enforceDefine: true,
paths: {
jquery: [
'http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min',
//If the CDN location fails, load from this location
'lib/jquery'
]
}
});
require(['jquery'], function ($) {
});
I am using the same method but I get an error instead, below is my code
requirejs.config({
baseUrl: location.protocol + '//' + location.host + '/app',
waitSeconds: 0,
paths: {
'jquery': ['https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0-alpha1/jquery.min','/assets/js/vendor/jquery'],
'jqueryPjax': '/assets/js/vendor/jquery.pjax',
'jqueryUI': '/assets/js/vendor/jquery-ui.min',
'jqueryMousewheel': '/assets/js/jquery.mousewheel',
'jScrollPane': '/assets/js/jquery.jscrollpane.min',
'fastclick': '/assets/js/vendor/fastclick',
'jquerySlidebars': '/assets/js/jquery.slidebars.min',
'imagesLoaded': '/assets/js/imagesloaded.pkgd.min',
'fancyBox': '/assets/js/jquery.fancybox.pack',
'fancyBoxThumb': '/assets/js/jquery.fancybox-thumbs',
'text': '/assets/js/vendor/text',
'chosen': '/assets/js/vendor/chosen',
'bb': '/assets/js/vendor/backbone-min',
'underscore': '/assets/js/vendor/underscore-min',
'angular': '/assets/js/angular.min',
'ventFactory': 'base/ventFactory',
'util': 'base/util',
'dom': 'base/dom',
'actionHandler': 'base/actionHandler',
'ajax': 'base/ajax'
},
shim: {
'jquery': {
exports: 'jQuery'
},
'jqueryUI': {
deps: ['jquery']
},
'angular': {
exports: 'angular'
},
'jqueryPjax': {
deps: ['jquery'],
exports: 'jQuery.fn.pjax'
},
'jqueryMousewheel': {
deps: ['jquery'],
exports: 'jQuery.fn.mousewheel'
},
'jScrollPane': {
deps: ['jqueryMousewheel'],
exports: 'jQuery.fn.jScrollPane'
},
'jquerySlidebars': {
deps: ['jquery'],
exports: 'jquerySlidebars'
},
'fancyBox': {
deps: ['jquery'],
exports: 'fancyBox'
},
'fancyBoxThumb': {
deps: ['jquery', 'fancyBox'],
exports: 'fancyBoxThumb'
},
'chosen': {
deps: ['jquery'],
exports: 'chosen'
}
}
});
requirejs(['jquery', 'app'], function($, app) {
$(function() {
app.start();
});
});
I have just made the changes for Jquery as of now and I am giving both CDN URL and local path but when I load my page I get an error
TypeError: $el.siblings is not a function
Adding on
I am using Require JS for loading my libs but then at the production I am using almond, which combines all modules into one single file, so has this something to do with the error ?
Any help on this is highly appreciated. Thanks
Adding on I am using Require JS for loading my libs but then at the production I am using almond, which combines all modules into one single file, so has this something to do with the error ?
Yes, it does. Almond cannot do dynamic loading. In other words, everything you want Almond to load must be into a single bundle of modules. You cannot use a CDN with Almond.
"No dynamic loading" is the first restriction in its list of restrictions.

Handlebars isn't getting exported?

Problem
When executing the compiled handlebars templates the global Handlebars object isn't exported. NOTE: the global Backbone object is working.
See, when the code App.templates.todos attempts to execute in the todos.js file it fails because App.templates.todos isn't defined. Well ultimately that's because the third line in the templates.js file can't execute because the global Handlebars object isn't defined.
Why wouldn't that object get defined? What did I do wrong with require.js here?
UPDATE: I've verified that the handlebars.runtime.js file is in fact executing before the templates.js file and so require.js is running them in the right order when loading the todos.js file.
Bower Components
{
"name": "todomvc-backbone-requirejs",
"version": "0.0.0",
"dependencies": {
"backbone": "~1.1.0",
"underscore": "~1.5.0",
"jquery": "~2.0.0",
"todomvc-common": "~0.3.0",
"backbone.localStorage": "~1.1.0",
"requirejs": "~2.1.5",
"requirejs-text": "~2.0.5",
"handlebars": "~2.0.0"
},
"resolutions": {
"backbone": "~1.1.0"
}
}
main.js
/*global require*/
'use strict';
// Require.js allows us to configure shortcut alias
require.config({
// The shim config allows us to configure dependencies for
// scripts that do not call define() to register a module
shim: {
backbone: {
deps: [
'underscore',
'jquery'
],
exports: 'Backbone'
},
backboneLocalstorage: {
deps: ['backbone'],
exports: 'Store'
},
handlebars: {
exports: 'Handlebars'
},
templates: {
deps: ['handlebars'],
exports: 'App'
},
underscore: {
exports: '_'
}
},
paths: {
jquery: '../bower_components/jquery/jquery',
underscore: '../bower_components/underscore/underscore',
backbone: '../bower_components/backbone/backbone',
backboneLocalstorage: '../bower_components/backbone.localStorage/backbone.localStorage',
handlebars: '../bower_components/handlebars/handlebars.runtime',
templates: '../../../templates',
text: '../bower_components/requirejs-text/text'
}
});
require([
'backbone',
'views/app',
'routers/router'
], function (Backbone, AppView, Workspace) {
/*jshint nonew:false*/
// Initialize routing and start Backbone.history()
new Workspace();
Backbone.history.start();
// Initialize the application view
new AppView();
});
todos.js
/*global define*/
define([
'jquery',
'backbone',
'handlebars',
'templates',
'common'
], function ($, Backbone, Handlebars, Templates, Common) {
'use strict';
var TodoView = Backbone.View.extend({
tagName: 'li',
template: App.templates.todos,
...
});
return TodoView;
});
templates.js
this["App"] = this["App"] || {};
this["App"]["templates"] = this["App"]["templates"] || {};
this["App"]["templates"]["stats"] = Handlebars.template({"1":function(depth0,helpers,partials,data) {
From official documentation of RequireJS:
The shim config only sets up code relationships. To load modules that
are part of or use shim config, a normal require/define call is
needed. Setting shim by itself does not trigger code to load.
So first you need to somehow call the Handlebars and after try to use it in templates.js.

Angular applications powered by Requirejs - Argument '(contoller)' is not a function, got undefined?

I am trying to work on an Angular application powered by RequireJS, but I am not able to split up the controller files as I keep getting an error of Argument '(contoller)' is not a function, got undefined. Any idea what have I done wrong?
app/main.js,
require.config({
baseUrl: "",
// alias libraries paths. Must set 'angular'
paths: {
'domReady': 'bower_components/requirejs-domready/domReady',
'angular': 'bower_components/angular/angular',
'angular-route': 'bower_components/angular-route/angular-route',
'jquery': 'bower_components/jquery/dist/jquery'
},
// Add angular modules that does not support AMD out of the box, put it in a shim
shim: {
'angular': {
exports: 'angular'
},
'angular-route': {
exports: 'angular'
}
},
// kick start application
deps: ['app/bootstrap']
});
app/app.js,
define([
'angular',
'angular-route',
'jquery'
], function (ng,ngRoute,$) {
'use strict';
console.log($('h1').length);
return ng.module('app', ['ngRoute']).
config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/home', {
templateUrl: 'view/home.html',
controller: 'HomeCtrl',
controllerUrl: 'app/home'
});
$routeProvider.when('/view1', {
templateUrl: 'view/view1.html',
controller: 'View1Ctrl',
controllerUrl: 'app/view'
});
//$routeProvider.otherwise({redirectTo: '/home'});
}]);
});
app/home.js,
define(['app/app'], function (app) {
app.controller('HomeCtrl', function ($scope) {
$scope.message = "Message from HomeCtrl";
});
});
error,
Error: [ng:areq] Argument 'HomeCtrl' is not a function, got undefined
But if I concat the controllers after ng.module('app', ['ngRoute']).config(...) then they work fine,
app/app.js,
define([
'angular',
'angular-route',
'jquery'
], function (ng,ngRoute,$) {
'use strict';
console.log($('h1').length);
return ng.module('app', ['ngRoute']).
config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/home', {
templateUrl: 'view/home.html',
controller: 'HomeCtrl',
//controllerUrl: 'app/home'
});
$routeProvider.when('/view1', {
templateUrl: 'view/view1.html',
controller: 'View1Ctrl',
//controllerUrl: 'app/view'
});
//$routeProvider.otherwise({redirectTo: '/home'});
}]).controller('HomeCtrl', function ($scope) {
$scope.message = "Message from HomeCtrl";
}).controller('View1Ctrl', function ($scope) {
$scope.message = "Message from View1Ctrl";
});
});
Why??
This seems to be a problem with the load order of your JS files. You are defining the HomeCtrl in app/home.js and using it it app/app.js. So make sure that home.js is loaded before app.js in your web app.
Split the app.js into two parts - one for just creating the ng.module (module.js), and one for setting the config (module-config.js). Then the dependency tree will be:
app/module-config.js
requires: app/home.js
requires: app/module.js

Marionette v2.2 upgrade error - Cannot read property 'ChildViewContainer' of undefined

I've started a new backbone, marionette and require project using version 2.2 (i previously worked with 1.8) It seems a lot has changed. I'm getting an error when the browser loads marionette:
Uncaught TypeError: Cannot read property 'ChildViewContainer' of undefined
This is my main.js file:
require.config({
baseURL: 'scripts',
paths: {
"jquery": "lib/jquery",
"underscore": "lib/underscore",
"backbone": "lib/backbone",
"marionette": 'lib/backbone.marionette',
"templates": "../templates",
"text": "lib/text"
},
shim: {
underscore: {
exports: '_'
},
backbone: {
deps: ['underscore', 'jquery'],
exports: 'Backbone'
},
marionette: {
deps: ['jquery', 'underscore', 'backbone'],
exports: 'Marionette'
},
waitSeconds: 15
}
});
require([ "app", "marionette"], function(App, marionette) {
App.start();
});
And this is my app.js file:
define(["marionette", "router"], function (Marionette, AppRouter) {
var MyApp = Marionette.Application.extend({
initialize: function(options) {
console.log("options.container");
}
});
var MyApp = new MyApp({container: '#page'});
MyApp.addInitializer(function (options) {
MyApp.Router = new AppRouter();
Backbone.history.start();
});
// export the app from this module
return MyApp;
});
Just look at your backbone.js file. It's empty. Download backbone.js from http://backbonejs.org/ and replace it.
I just ran into this same issue myself. The issue was multiple instances of Marionette being included on the page. (i had errantly placed a script tag for marionette on the page from cdnjs, as well as trying to include the static file locally via require). removing the reference to the external JS file helped me...

Uncaught Error: No module: MyApp

I load AngularJs and jQuery using RequireJs in nodeJs framework.
That is main.js
require.config({
paths: {
angular: 'vendor/angular.min',
bootstrap: 'vendor/twitter/bootstrap',
jquery: 'vendor/jquery-1.9.0.min',
domReady: 'vendor/require/domReady',
underscore: 'vendor/underscore.min'
},
shim: {
angular: {
deps: [ 'jquery' ],
exports: 'angular'
}
}
});
require([
'app',
'angular-boot'
], function() {
});
in app.js
define(['angular'], function (angular) {
return angular.module('MyApp', []);
})
and in angular-boot.js
define([ 'angular', 'domReady' ], function (angular, domReady) {
domReady(function() {
angular.bootstrap(document, ['MyApp']);
});
});
In my html file I have only this line, in order to declare and use requirejs.
Not ng-ap or anything else.
<script data-main="js/main" src="js/require.js"></script>
The problem is that sometimes runs, sometimes not.
The error when it doesn't run is
Uncaught Error: No module: MyApp
If there is any thought about it, I would really appreciate it.
Thank you very much.
In your shim, you need to setup the app as a dependency to angular-boot. Your angular-boot file depends on app (where MyApp is defined), and because the load order for these two files is not specified, sometimes angular-boot loads before the app and thus produces that error.
To remedy, just update your shim as such:
shim: {
angular: {
deps: [ 'jquery' ],
exports: 'angular'
},
'angular-boot': {
deps: ['app']
}
}
and than, since you don't need to include the 'app' explicitly your require call can be reduced to:
require(['angular-boot']);

Categories

Resources