How to import requireJS modules by name in angularJS - angularjs
Assume in an Angular project we have added all controllers as modules by require.js:
// js/controllers/modules.js
define("appControllers", ['angular'], function (ng) {
'use strict';
return ng.module('app.controllers', []);
});
and all controllers are defined in separated files
// js/controllers/home-controller.js
define(['appControllers'], function (controllers) {
'use strict';
controllers.controller('HomeController', ['$scope', function ($scope) {
// my logics here
}]);
});
usage in application
// js/app.js
define([
'angular',
'./controllers'
], function (angular) {
'use strict';
return angular.module('app', [
'app.controllers'
]);
});
This works very fine as long as controllers are in js/controllers directory. but apparently it doesn't work after grunt minifies JS files into a single main.min.js file.
How to change this code to work in a single minified main.min.js file?
Additional context
I tried to use the name of modules instead of their path, but I couldn't get it to work.
I get this error :
http://127.0.0.1:9001/javascripts/appControllers.js
Uncaught Error: Script error for "appControllers", needed by: app
maybe too late.but for loading requireJs modules by name you can call requirejs.config() method before bootstrapping angular.
sample code :
// before bootstrapping ...
requirejs.config({
waitSeconds:60,
baseUrl: exports.paths.scripts.in.get(),
paths: {
"jquery": bowerComponents + "jquery/dist/jquery.min",
"tinymce": bowerComponents + "tinymce/tinymce.min",
"angular-tinymce": bowerComponents + "angular-ui-tinymce/dist/tinymce.min",
"angular": bowerComponents + "angular/angular.min",
"angular-ui-router": bowerComponents + "angular-ui-router/release/angular-ui-router.min",
"angular-re-tree": bowerComponents + "re-tree/re-tree.min",
"angular-device-detector": bowerComponents + "ng-device-detector/ng-device-detector.min",
"angular-messages": bowerComponents + "angular-messages/angular-messages.min",
"angular-local-storage": nodeModules + "angular-local-storage/dist/angular-local-storage.min",
"angular-resource": bowerComponents + "angular-resource/angular-resource.min",
"adm-dtp": bowerComponents + "adm-dtp/dist/ADM-dateTimePicker.min",
"angular-animate": nodeModules + "angular-animate/angular-animate.min",
"angular-aria": nodeModules + "angular-aria/angular-aria.min",
"angular-material": nodeModules + "angular-material/angular-material.min",
"material-steppers": nodeModules + "md-steppers/dist/md-steppers.min",
"angular-sanitize": nodeModules + "angular-sanitize/angular-sanitize.min",
"spin": nodeModules + "angular-spinner/node_modules/spin.js/spin.min",
"angular-spinner": nodeModules + "angular-spinner/angular-spinner.min",
"angular-resizable": nodeModules + "angular-resizable/src/angular-resizable",
"ng-file-upload": nodeModules + "ng-file-upload/dist/ng-file-upload.min",
"angular-material-icons": nodeModules + "angular-material-icons/angular-material-icons.min",
"underscore": bowerComponents + "underscore/underscore-min",
"jquery-nanoscroller": bowerComponents + "angular-nanoscroller/jquery.nanoscroller.min",
"angular-nanoscroller": bowerComponents + "angular-nanoscroller/scrollable",
"angular-material-data-table": bowerComponents + "angular-material-data-table/dist/md-data-table",
"element-queries": nodeModules + "css-element-queries/src/ElementQueries",
"jquery-resize": "vendors/jquery.resize",
"jquery-print": "vendors/jQuery.print",
"ng-scrollable": "vendors/ng-scrollable",
"angular-truncate": "vendors/truncate",
"string": nodeModules + "string/dist/string.min",
"masonry": bowerComponents + "masonry/dist/masonry.pkgd.min"
},
shim: {
"jquery": {
deps: [],
exports: "$"
}, "jquery-resize": {
deps: ["jquery"],
exports: "$"
}, "jquery-print": {
deps: ["jquery"],
exports: "$"
}, "jquery-nanoscroller": {
deps: ["jquery"],
exports: "$"
}, "angular": {
deps: [],
exports: "angular"
}, "angular-ui-router": {
deps: ["angular"],
exports: "angular"
}, "angular-tinymce": {
deps: ["angular","tinymce"],
exports: "angular"
}, "tinymce": {
deps: [],
exports: "tinyMCE"
}, "angular-local-storage": {
deps: ["angular"],
exports: "angular"
}, "angular-animate": {
deps: ["angular"],
exports: "angular"
}, "angular-aria": {
deps: ["angular"],
exports: "angular"
}, "angular-material": {
deps: ["angular"],
exports: "angular"
},"material-steppers": {
deps: ["angular"],
exports: "angular"
}, "angular-material-icons": {
deps: ["angular"],
exports: "angular"
}, "angular-re-tree": {
deps: ["angular"],
exports: "angular"
}, "angular-device-detector": {
deps: ["angular-re-tree"],
exports: "angular"
}, "angular-resizable": {
deps: ["angular"],
exports: "angular"
}, "angular-messages": {
deps: ["angular"],
exports: "angular"
}, "angular-truncate": {
deps: ["angular"],
exports: "angular"
}, "angular-sanitize": {
deps: ["angular"],
exports: "angular"
}, "angular-resource": {
deps: ["angular"],
exports: "angular"
},"ng-file-upload": {
deps: ["angular"],
exports: "angular"
}, "adm-dtp": {
deps: ["angular"],
exports: "angular"
}, "angular-nanoscroller": {
deps: ["angular", "jquery-nanoscroller"],
exports: "angular"
}, "angular-material-data-table": {
deps: ["angular","angular-material"],
exports: "angular"
}, "ng-scrollable": {
deps: ["angular"],
exports: "angular"
}
}
});
//requirejs module resolution by name + bootstrapping angular ....
define(["jquery",
"angular",
"angular-ui-router",
"angular-animate",
"angular-aria",
"angular-material",
"material-steppers",
"angular-device-detector",
"angular-resizable",
"angular-messages",
"angular-local-storage",
"underscore",
"element-queries",
"string",
"jquery-resize",
'angular-material-icons',
'angular-spinner',
'angular-nanoscroller',
'angular-truncate',
'angular-sanitize',
'angular-resource',
'jquery-print',
'ng-file-upload',
'adm-dtp',
'angular-material-data-table',
'ng-scrollable',
'tinymce',
'angular-tinymce',
"masonry"],
function (jquery,
angular,
angularUiRouter,
angularAnimate,
angularAria,
angularMaterial,
materialSteppers,
angularDeviceDetector,
angularResizable,
angularMessages,
angularLocalStorage,
underscore,
elementQueries,
string,
jqueryResize,
angularMaterialIcons,
angularSpinner,
angularNanoScroller,
angularTruncate,
angularSanitize,
angularResource,
jqueryPrint,
ngFileUpload,
admDateTimePicker,
angularMaterialDataTable,
ngScrollable,
tinyMce,
angularTinyMce,
masonry) {
var app = angular.module("app", ['ui.router', 'ngMaterial', 'ngMessages', 'LocalStorageModule', 'angularResizable', 'ng.deviceDetector', 'ngMdIcons', 'angularSpinner', 'sun.scrollable', 'md.data.table', 'truncate', 'ngResource', 'ngScrollable', "ngSanitize", "ngAnimate", 'ADM-dateTimePicker', 'ngFileUpload','md-steppers','ui.tinymce'],
function config() {
});
app.run(function ($rootScope, $state,security,materialDataTable,state) {
$rootScope.$on('$stateChangeStart', function (event, toState) {
if (toState.data && toState.data.secure && !security.isAuthenticated()) {
$state.go("root.login");
event.preventDefault();
}
});
$rootScope.$on('$stateChangeSuccess', function (event, toState) {
if(toState.data.resetDataContextAfterStateActivated) {
//create new context or reset preexist context
materialDataTable.getContext(state.current.getDataServiceName(), state.current.getDataService(),true);
}
});
});
var afterBootstrapTasks = [];
function startAngular() {
var root = document.getElementsByTagName("body")[0];
angular.bootstrap(root, ["app"]);
var injector = angular.element(root).injector();
afterBootstrapTasks.forEach(function (item) {
item(injector);
});
}
return {
jquery: jquery,
angular: angular,
angularUiRouter: angularUiRouter,
underscore: underscore,
elementQueries: elementQueries,
jqueryResize: jqueryResize,
string: string,
masonry: masonry,
app: app,
startAngular: startAngular,
storage: angularLocalStorage,
directives: [],
afterBootstrapTasks: afterBootstrapTasks,
tinyMce:tinyMce,
};
});
this was the script loading part of my last angular js project that I was working on it last year. now everything is changed. and angularjs is not my favorite javascript framework. I hope my answer can be helpful.
Related
How to load third party libraries using Require.js in Angular.js project
Really don't understand how to load third party libraries using Require.js in Angular.js project For example 'topojson' is defined, but 'datamap' is undefined in this case. Datamap from here https://github.com/markmarkoh/datamaps/blob/master/dist/datamaps.world.js Topojson from here https://github.com/mbostock/topojson/blob/master/topojson.js Angular app.js: 'use strict'; requirejs.config({ paths: { 'angular': ['../lib/angularjs/angular'], 'angular-route': ['../lib/angular-route/angular-route'], 'angular-resource': ['../lib/angular-resource/angular-resource'], 'angular-animate': ['../lib/angular-animate/angular-animate'], 'datamap':['../app/dense/world-view/datamaps.world'], 'topojson':['../app/dense/world-view/topojson'], 'lodash': ['../lib/lodash/lodash'], 'd3': ['../lib/d3js/d3'] }, shim: { 'angular': { exports: 'angular' }, 'angular-route': { deps: ['angular'], exports: 'angular' }, 'angular-resource': { deps: ['angular'], exports: 'angular' }, 'angular-animate': { deps: ['angular'], exports: 'angular' }, 'd3': { exports: 'd3' }, 'topojson': { deps: ['d3'], exports: 'topojson' }, 'datamaps': { deps: ['d3', 'topojson'], exports: 'datamaps' }, 'lodash': { exports: 'lodash' } } }); require( [ 'angular', 'topojson', 'datamap', 'angular-route', 'angular-resource', 'angular-animate', 'lodash', 'd3' ], function (angular, topojson, datamap) { console.log("topojson", topojson); console.log("datamap", datamap); // is undefined angular.module('myApp', [ 'myApp.graph', 'myApp.node', 'myApp.dense', 'ngAnimate', 'ngRoute']) .config(function ($routeProvider) { $routeProvider.otherwise({ redirectTo: '/login' }); }) ; angular.bootstrap(document.getElementById("myAppId"), ['myApp']); }); Some of the Angular controllers: 'use strict'; define(['angular'], function (angular) { angular .module('myApp.dense', ['ngRoute']) .config(['$routeProvider', function ($routeProvider) { $routeProvider.when('/dense', { templateUrl: 'assets/app/dense/dense.html', controller: 'DenseCtrl' }); }]) .controller('DenseCtrl', function ($scope) { var map = new Datamap({ scope: 'world', element: document.getElementById("someId"), projection: 'mercator', height: 500, fills: { defaultFill: '#f0af0a', lt50: 'rgba(0,244,244,0.9)', gt50: 'red' }, data: { } }); }) ; }); In my angular controller new Datamap(...) says 'ReferenceError: Datamap is not defined' This is not the only case. Same for most external JS libraries. I am running Angular project on top of Scala and SBT with WebJars, so Require.js is the only way how to load all that stuff.
I don't see any imports except for angular in your RequireJS module (the second snippet in your question). You need to add your other dependencies, such as datamap, etc.
Looks like in 'Datamap' object does not initialize, line 12535: https://github.com/markmarkoh/datamaps/blob/master/dist/datamaps.world.js#L12535 // expose library if (typeof exports === 'object') { d3 = require('d3'); topojson = require('topojson'); module.exports = Datamap; } else if ( typeof define === "function" && define.amd ) { define( "datamaps", ["require", "d3", "topojson"], function(require) { d3 = require('d3'); topojson = require('topojson'); return Datamap; }); // window.Datamap = window.Datamaps = Datamap; // hack } else { window.Datamap = window.Datamaps = Datamap; } Now it works for me. Added that line after define: window.Datamap = window.Datamaps = Datamap; // hack and used require block inside Angular controller: requirejs(["datamaps"], function () { // draw map here new Datamap({...}) };
Angular-Material with RequireJs
today I'm tryng to configure angular material with requirejs but I receive an annoing problem: Error: ngMaterial requires HammerJS to be preloaded. This's my configurator file: require.config paths: jquery: "../bower_components/jquery/dist/jquery" domReady: "../bower_components/requirejs-domready/domReady" underscore: "../bower_components/underscore/underscore" store: "../bower_components/store-js/store" moment: "../bower_components/moment/min/moment-with-langs" jsonPath: "../libs/jsonpath-0.8.0" es5Shim: "../bower_components/es5-shim/es5-shim" consoleShim: "../bower_components/console-shim/console-shim" json3: "../bower_components/json3/lib/json3.min" promise: "../bower_components/es6-promise/promise.min" hammer: "../bower_components/hammerjs/hammer" angular: "../bower_components/angular/angular" ngAnimate: "../bower_components/angular-animate/angular-animate.min" ngAria: "../bower_components/angular-aria/angular-aria.min" ngMaterial: "../bower_components/angular-material/angular-material" ngRoute: "../bower_components/angular-route/angular-route" baseObject: "scripts/helpers/base-object" app: "scripts/app/app" env: "../env" shim: hammer: exports: "Hammer" angular: exports: "angular" deps: [ "jquery" ] ngRoute: exports: "angularRoute" deps: [ "angular" ] ngAnimate: exports: "angularAnimate" deps: [ "angular" ] ngAria: exports: "angularAria" deps: [ "angular" ] ngMaterial: exports: "angularMaterial" deps: ["Hammer", "angular"] underscore: exports: "_" jsonPath: exports: "jsonPath" promise: exports: "Promise" deps: [ "jquery","hammer", "angular", "ngMaterial", "ngAnimate", "ngAria", "consoleShim", "es5Shim", "consoleShim", "json3", "underscore", "baseObject", "promise", "env" ] What's wrong???
I had the same issue, you can hack it with this solution: https://github.com/angular/material/issues/456 What you need is just to wrrap the hammer.js with this proxy. it worked for me, here is the require file: 'hammer': 'lib/hammerjs/hammer.min', 'hammerProxy': 'js/requirejs-proxy/hammer-proxy', ... 'angularMaterial': { deps: ['angular', 'angular-animate', 'hammerProxy', 'angular-aria'] } and here is hammer-proxy.js file: define(['hammer'], function (Hammer) { this.Hammer = Hammer; return Hammer; }); Let me know if you need any help with implamintation.
module not available using requirejs+angular
I have app.js file with the following config: require.config({ paths: { // vendors 'angular': 'vendor/angular', 'ngResource': 'vendor/angular-resource.min', 'ngRoute': 'vendor/angular-route.min', 'ngAnimate': 'vendor/angular-animate.min' }, shim: { ngAnimate: { deps: ['angular'] }, angular: { deps: [], exports: 'angular' }, ngRoute: { deps: ['angular'] }, ngResource: { deps: ['angular'] } }, baseUrl: 'scripts' }); Now i'm trying to instantiate angular trough require: define("app", ["angular", "ngResource"], function (angular) { var app = angular.module("app", ["ngResource"]); // you can do some more stuff here like calling app.factory()... return app; }); But it throws out: Module 'app' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument. I'm following this guide step-by-step. What am i doing wrong here?
ngReactGrid issue within requirejs
Experimenting with ngReactGrid I've got stuck on an issue where the grid component (ngReactGrid.js:38) throws an error of React is undefined. What could cause this, as the requirejs setup file includes "shim": { "angular": { exports: 'angular' }, 'react': { exports: 'React' }, "ngReactGrid": { deps: ['angular', 'react'] } } http://plnkr.co/edit/MwxbGnx1xu3gxfhY7ENM The same code outside of requirejs works as it should.
Checkout plnkr require.config({ "baseUrl": "/js", "paths": { "angular": "https://code.angularjs.org/1.3.0-beta.5/angular", "react": "http://fb.me/react-0.10.0", "ngReactGrid": "https://rawgit.com/josebalius/ngReactGrid/master/build/js/ngReactGrid", 'app': 'http://run.plnkr.co/zmcl7fFM2eAPf9Ew/app' }, "shim": { "angular": { exports: 'angular' }, "ngReactGrid": { deps: ['angular', 'react'] } } }); require(['app'], function( app) { var $html = angular.element(document.getElementsByTagName('html')[0]); angular.element().ready(function() { angular.bootstrap($html, [app.name]); }); }); Hope this will help
Backbone.io, Backbone, and require.js
How can I load Backbone.io, Backbone, and socket.io with Require.js's shim config? It seems like everything else is loading just fine, just that when I attempt to run Backbone.io.connect() I get "Backbone is not defined". Backbone.io is served the same way socket.io is from the /socket.io directory that the socket.io server creates. requirejs.config({ baseUrl: 'javascripts/lib', paths: { jquery: 'jquery.min', bootstrap: 'bootstrap.min' }, shim : { 'underscore': { exports: '_' }, 'backbone': { deps: ["underscore", "jquery"], exports: 'Backbone' }, 'bootstrap': { deps: ["jquery"] } } }) requirejs(['jquery', 'underscore', 'backbone', 'bootstrap', '../socket.io/socket.io.js', '../socket.io/backbone.io.js' ], function($, _, Backbone, bootstrap){ Backbone.io.connect(); } small update: It seems like Backbone is defined just fine in the main requirejs function, it's just that backbone.io needs Backbone to be defined before it's initialized. How can I initialize the Backbone object and THEN the backbone.io library so it can do it's thing?
Try including backbone in your path paths: { jquery: 'jquery.min', bootstrap: 'bootstrap.min', underscore: '<name of underscore file>', backbone: '<name of backbone file>' }, I think that should do it. Remember not to include the .js in the file name. Also, if backbone.io depends on backbone you may need to add the dependencies under shim. shim : { 'underscore': { exports: '_' }, 'backbone': { deps: ["underscore", "jquery"], exports: 'Backbone' }, 'bootstrap': { deps: ["jquery"] }, 'backbone.io': { deps: ["backbone"] } }
Here's how it ended up working for me: Thanks landland, your answer helped the most. requirejs.config({ baseUrl: 'javascripts/lib', paths: { jquery: 'jquery.min', bootstrap: 'bootstrap.min', backbone: 'backbone', underscore: 'underscore', socketio: '../../socket.io/socket.io', backboneio: '../../socket.io/backbone.io' }, shim : { 'underscore': { exports: '_' }, 'backbone': { deps: ["underscore", "jquery"], exports: 'Backbone' }, 'bootstrap': { deps: ["jquery"], exports: 'bootstrap' }, 'backboneio': { deps: ["backbone", "socketio"] } } }) requirejs(['jquery', 'underscore', 'backbone', 'bootstrap', 'socketio', 'backboneio' ], function($, _, Backbone, bootstrap, titlealert, waitForImages){ }