Require and Angular RouteProvider undefined - angularjs

I get undefined in the following code when trying to load via require.js
HTML
<script data-main="application/main" src="http://requirejs.org/docs/release/2.1.14/minified/require.js"></script>
main.js
require.config({
baseUrl: "application",
paths: {
angular: 'https://code.angularjs.org/1.4.5/angular',
angularRoute: 'https://code.angularjs.org/1.4.5/angular-route'
},
shim: {
angular: {exports: 'angular' } ,
angularRoute: { deps: ['angular'], exports: 'angularRoute' },
}
});
require(['app', 'routesBoot'], function (app) {
app.init();
});
app.js
define(['angular'], function (angular) {
var app = angular.module('reporterdashboard', []);
app.init = function () {
console.log('app.init called');
angular.bootstrap(document, ['reporterdashboard']);
};
return app;
});
routesBoot.js
require(['app', 'angularRoute'], function (app, angularRouterParam) {
//put my routes in here, using angularRouterParam
//but angularRouterParam = undefined
return app.config(function (angularRouterParam) {
angularRouterParam.when('/page2', { controller: 'Page2Controller', templateUrl: 'page2.html' });
});
});
When I inspect angularRouterParam passed into routesBoot it's undefined. What have I done wrong ?
I'm basically trying to split my app and therefore, placing my routes in their own file (controllers, directives etc will live in their own boot .js files). I'm letting require.js look after all my .js file loading as can be seen in main.js.
The code in routesBoot is not syntactically correct at the moment as I'm stuck with the problem of an undefined angularRouterParam

The problem was out side of the code I've posted here. I was loading a directive first into the index.html (View First). This directive was loading other dependencies. The project is quite large, some 40 .js files. My restructuring with require was at fault.

Related

AngularJS- Dynamic Loading of script files using LazyLoad- Webpack

Right now in my index.html page I have links to two CDN files one being a JS and the other a CSS file.
i.e.
in the the bottom of my body
https://somedomain.com/files/js/js.min.js
and in the head
https://somedomain.com/files/css/css.min.css
But right now they aren't needed on my homepage but just in one particular route. So I was looking into how I can lazy load these CDN resources when that routes gets hit i.e. /profile and only then ?
These aren't installed via bower or npm but just loaded via CDN url for example jquery. How in Angular 1 and Webpack can I lazy load that based on a route ?
Here you go.. It is made possible using oclazyload. Have a look at below code. A plunker linked below
I have a module Called myApp as below
angular.module('myApp', ['ui.router','oc.lazyLoad'])
.config(function ($stateProvider, $locationProvider, $ocLazyLoadProvider) {
$stateProvider
.state("home", {
url: "/home",
templateUrl: "Home.html",
controller: 'homeCtrl',
resolve: {
loadMyCtrl: ['$ocLazyLoad', function ($ocLazyLoad) {
return $ocLazyLoad.load('homeCtrl.js');
}]
}
})
.state("profile", {
url:"/profile",
templateUrl: "profile.html",
resolve: {
loadMyCtrl: ['$ocLazyLoad', function ($ocLazyLoad) {
return $ocLazyLoad.load('someModule.js');
}]
}
})
});
I have another module called someApp as below
(function () {
var mynewapp=angular.module('someApp',['myApp']);
mynewapp.config(function(){
//your code to route from here!
});
mynewapp.controller("profileCtrl", function ($scope) {
console.log("reached profile controller");
});
})();
I have a Live Plunker for your demo here
I have this JStaticLoader repo, to ease me loading static files whenever I need them. Though, it's not angularized, but you can still use it in your app as a directive, direct call it from your controller or even in the $rootScope to load your desired js.
JStaticLoader uses pure js and require no dependencies. It uses XMLHttpRequest to load the static files.
As an example use in your app.js (on $routeChangeStart or $stateChangeStart)
myApp
.run(['$rootScope', '$http', function ($rootScope, $http) {
var scriptExists = function (scriptId) {
if (document.getElementById(scriptId)) {
return true;
}
return false;
};
var addLazyScript = function (scriptId, url) {
if (scriptExists(scriptId)) return;
var js = document.createElement('script'),
els = document.getElementsByTagName('script')[0];
js.id = scriptId;
js.src = url;
js.type = "text/javascript";
els.parentNode.insertBefore(js, els);
};
$rootScope.$on('$routeChangeStart', function (e, current) {
if (current.controller === 'MainCtrl') {
var pathUrls = ["https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.8/js/materialize.js"],
scriptId = 'lazyScript1';
if (scriptExists(scriptId)) return;
JStaticLoader(pathUrls, { files: ['js'] }, function (vals, totalTime) {
/* Success */
for (var i = 0; i < vals.length; i++) {
var path = vals[i];
addLazyScript(scriptId, path);
}
}, function (error, totalTime) {
/* Error */
console.warn(error, totalTime);
});
}
});
}]);
On the sample above, I get a js file by using xhr, and append it as a script in my document once it's finished. The script will then be loaded from your browser's cache.
Strictly talking about the Webpack -
Webpack is just a module bundler and not a javascript loader.Since it packages files only from the local storage and doesn't load the files from the web(except its own chunks).ALthough other modules may be included into the webpack which may do the same process.
I will demonstrate only some of the modules which you can try,as there are many such defined on the web.
Therefore a better way to lazy load the cdn from the another domain would be using the javascript loader - script.js
It can be loaded in the following way -
var $script = require("script.js");
$script = ("https://somedomain.com/files/js/js.min.js or https://somedomain.com/files/css/css.min.css",function(){
//.... is ready now
});
This is possible because the script-loader just evaluates the javascript in the global context.
References here
Concerning about the issue of lazy loading the cdn into the angular app
The following library Lab JS is made specifically for this purpose.
It becomes very simple to load and bloack the javascript using this library.
Here is an example to demonstrate
<script src="LAB.js"></script>
<script>
$LAB
.script("/local/init.js").wait(function(){
waitfunction();
});
<script>
OR
You can use the require.js
Here is an example to load the jquery
require.config({
paths: {
"jquery": "https://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min"
},
waitSeconds: 40
});
You should also consider the following paragraph from this article.
Loading third party scripts async is key for having high performance web pages, but those scripts still block onload. Take the time to analyze your web performance data and understand if and how those not-so-important content/widgets/ads/tracking codes impact page load times.

No module and Modernizr error when adding angular to requirejs

Im trying to add AngularJS to my web application which already makes use of RequireJS. When loading my test page, i am seeing:
1) Error: No module: MyApp
...),factory:a("$provide","factory"),service:a("$provide","service"),value:a("$prov...
2) TypeError: Modernizr is undefined
if (!Modernizr.history) {
I am using AngularJS v1.1.5
Here's my tree:
resources
- CSS
- js
- controllers
- MainController.js
- libs
- angular.js
- jquery.js
- require.js
- mondernizr.js
......
......
......
main.js
mainApp.js
pages
test.html
main.js
(function(require) {
'use strict';
require.config({
baseUrl: '/resources/js',
paths: {
'zepto' : 'libs/zepto',
'jquery' : 'libs/jquery',
'angular' : 'libs/angular',
'router' : 'libs/page',
'history' : 'libs/history.iegte8',
'event' : 'libs/eventemitter2'
},
shim: {
'zepto' : { exports: '$' },
'angular' : { exports : 'angular' },
'router' : { exports: 'page'},
'modernizr' : { exports: 'Modernizr' }
}
});
require([ 'jquery', 'angular', 'routes', 'modernizr', 'event' ], function($, angular, routes, Modernizr, Event) {
function bootstrap() {
var app = new Event(),
router = routes(app);
if (typeof console !== 'undefined') console.info('>> module routes loaded ... executing router');
router({ click: false, popstate: false });
if (typeof console !== 'undefined') console.info('>> executed router');
}
$(function() {
if (!Modernizr.history) {
require([ 'history' ], bootstrap);
require([ 'controllers/MainController' ], bootstrap);
} else {
require([ 'controllers/MainController' ], bootstrap);
bootstrap();
}
});
});
})(this.require);
mainApp.js
define(['angular'], function(angular) {
return angular.module('MyApp', []);
})
MainController.js
require(['mainApp'], function(mainApp) {
mainApp.controller('MainController', function($scope) {
$scope.data = {message: "Hello"};
})
});
test.html
<!DOCTYPE html>
<html ng-app="MyApp">
<head>
<script src="/assets/js/vendor/require.js" data-main="/assets/js/main"></script>
</head>
<body>
<div ng-controller="MainController">
{{ data.message + " world" }}
</div>
</body>
</html>
Any help appreciated.
The No module: MyApp problem is causes by the Angular automatic initialization: <html ng-app="MyApp">. Angular loads before mainApp.js, sees the ng-app and tries to find a module which is not (yet) there.
The solution is to manually bootstrap Angular from within main.js and inside the document load event, as described here.
I am not sure about the problem with Modernizr; I guess you are NOT loading it at all. RequireJs is not complaining because of the shim. How are you loading it? It is not included in your paths configuration. You may want to load Modernizr as independent script before all other scripts (as per recommendations), in which case no paths configuration is needed and the shim is enough.

AngularJS and RequireJS: No module: myApp

I'm trying for the first time to use AngularJS in conjunction with RequireJS using this guide as a basis. As far I can tell after a lot of debugging I'm loading all my modules in the correct order, but when the application runs Angular throws an Error / Exception with the following message:
Argument 'fn' is not a function, got string from myApp
I've seen this message before due to syntax errors, so even though I've looked trough the code multiple times I won't rule out the possibility of a simple syntax error. Not making a Fiddle just yet in case it is something as simple as a syntax error, but I'll of course do so if requested.
Update: I just noticed when setting ng-app="myApp" in the <html> tag I also get an additional error,
No module: myApp
Update II: Okay, it turns out it indeed was an syntax error in the only file not included below. I am though still left with the problem from update I.
RequireJS bootstrap
'use strict';
define([
'require',
'angular',
'app/myApp/app',
'app/myApp/routes'
], function(require, ng) {
require(['domReady'], function(domReady) {
ng.bootstrap(domReady, ['myApp']);
});
});
app.js
'use strict';
define([
'angular',
'./controllers/index'
], function(ng) {
return ng.module('myApp', [
'myApp.controllers'
]);
}
);
controllers/index
'use strict';
define([
'./front-page-ctrl'
], function() {
});
controllers/module
'use strict';
define(['angular'], function (ng) {
return ng.module('myApp.controllers', []);
});
controllers/front-page-ctrl
'use strict';
define(['./module'], function(controllers) {
controllers.
controller('FrontPageCtrl', ['$scope',
function($scope) {
console.log('I\'m alive!');
}
]);
});
Delete ng-app="myApp" from your html.
Because it has bootstrapped manually
ng.bootstrap(domReady, ['myApp']);
RequireJS docs on Dom ready state:
Since DOM ready is a common application need, ideally the nested
functions in the API above could be avoided. The domReady module also
implements the Loader Plugin API, so you can use the loader plugin
syntax (notice the ! in the domReady dependency) to force the
require() callback function to wait for the DOM to be ready before
executing. domReady will return the current document when used as a
loader plugin:
So, when you require 'domReady' the result is a function:
function domReady(callback) {
if (isPageLoaded) {
callback(doc);
} else {
readyCalls.push(callback);
}
return domReady;
}
But when you append the domReady string with ! sign the result will be the actual document element:
'use strict';
define([
'require',
'angular',
'app/myApp/app',
'app/myApp/routes'
], function(require, ng) {
require(['domReady!'], function(domReady) {
// domReady is now a document element
ng.bootstrap(domReady, ['myApp']);
});
});

angular.js with require.js getting Uncaught Error: [$injector:modulerr]

I am trying to use require.js with Main.js and getting following error:
Uncaught Error: [$injector:modulerr] http://errors.angularjs.org/1.2.0rc1/$injector/modulerr?p0=MyApp&p1=Error%3…3A8080%2FResults%2Fresources%2Fjs%2Fvendor%2Fangular.min.js%3A31%3A252)
My Main.js
require.config({
// alias libraries paths
paths: {
'angular': 'vendor/angular.min',
'jquery': 'vendor/jquery-1.8.0-min',
'angularroute': 'vendor/angular-route'
},
// angular does not support AMD out of the box, put it in a shim
shim: {
'angular': {
deps: ['jquery'],
exports: 'angular'
},
'angularroute':{
deps:['angular']
}
}
});
require([
'angular',
'angularroute',
'app'
],
function(angular, angularroute, app){
'use strict';
})
My app.js
define(['angular'], function(angular){
return angular.module('MyApp',['ngRoute']);
});
I got an error that said I need to add angularroute to my app but I still get this error. Can anyone point me to what i might be doing wrong?
I found a solution here: https://github.com/tnajdek/angular-requirejs-seed/blob/master/app/js/main.js
from the docs:
http://code.angularjs.org/1.2.1/docs/guide/bootstrap#overview_deferred-bootstrap
window.name = "NG_DEFER_BOOTSTRAP!";
require(['angular', 'angularroute', 'app'], function(angular, angularroute, app){
'use strict';
//after you are done defining / augmenting 'MyApp' run this:
angular.element().ready(function() {
angular.resumeBootstrap([app['name']]);
});
})
Here is my require config, at require_config.js:
var require = {
baseUrl: '/js',
paths: {
'angular': 'lib/angular.min',
'angular.route': 'lib/angular-route.min',
'angular.resource': 'lib/angular-resource.min',
'angular.animate': 'lib/angular-animate.min',
'angular.ui.bootstrap': 'lib/ui-bootstrap-tpls-0.6.0.min',
'angular.upload': 'lib/ng-upload.min',
'jquery': 'lib/jquery-1.10.2.min'
},
shim: {
'angular': ['jquery'],
'angular.route': ['angular'],
'angular.resource': ['angular'],
'angular.animate': ['angular'],
'angular.ui.bootstrap': ['angular'],
'angular.upload': ['angular'],
'my.angular': ['angular', 'angular.route', 'angular.resource', 'angular.animate', 'angular.ui.bootstrap', 'angular.upload']
}
};
My script tags at HTML <head>:
<script src="/js/require-config.js"></script>
<script src="/js/lib/require.js"></script>
The pages that come from server-side MAY make usage of Angular, or jQuery, both, or none... so, the HTML markup may contain a single simple tag to eventually activate the whole Angular structure, like this:
<script>require(['myApp']);</script>
Now, at myApp.js, I just depend on my.angular, which takes care of loading everything else... in fact, I have other flavours of "my.angular", with different subsets, which I use in different contexts of the site:
define(['my.angular'], function() {
var myApp = angular.module('myApp', ['ngRoute', 'ngResource', 'ngAnimate', 'ngUpload', 'ui.bootstrap']);
// more app module stuff here, including bootstrap
return myApp;
});
angular is defined as a global variable and your declaration is overriding it. The file angular.js does not return anything so there is nothing to inject at the RequireJS level. Try the following:
define(['angular'], function(){
return angular.module('MyApp',['ngRoute']);
});
I was struggling with RequireJS and AngularJS so I created angularAMD to help me:
http://marcoslin.github.io/angularAMD/
Your setup looks fine, except you need to add angularroute as a dependency in the define portion of the app.js file. You mentioned this, but didn't reflect this in your sample code.
define(['angular', 'angularroute'], function(angular){
return angular.module('MyApp',['ngRoute']);
});

AngularJS directive loaded with RequireJS not compiling

I'm in the beginning stages of building a large app with AngularJS and RequireJS. Everything loads find but directives aren't manipulating the DOM as they should. No errors are being reported and rest of the app works fine: Views are loaded and $scope is bindable. Examining the console shows that all the files loaded. I'm assuming this is a lazy load issue in that my directive is simply not loading at the correct time. I'd appreciate any insight into how to properly load directives in this regard. Unless it's a part of Angular's jqLite, please refrain from suggesting jQuery.
config.js
require.config({
paths: { angular: '../vendor/angular' }
shim: { angular: { exports: 'angular' } }
});
require(['angular'], function(angular) {
angular.bootstrap(document, ['myApp']);
});
myApp.js
define(['angular', 'angular-resource'], function (angular) {
return angular.module('myApp', ['ngResource']);
});
routing.js
define(['myApp', 'controllers/mainCtrl'], function (myApp) {
return myApp.config(['$routeProvider', function($routeProvider) {
...
}]);
});
mainCtrl.js
define(['myApp', 'directives/myDirective'], function (myApp) {
return myApp.controller('mainCtrl', ['$scope', function ($scope) {
...
}]);
});
myDirective.js
require(['myApp'], function (myApp) {
myApp.directive('superman', [function() {
return {
restrict: 'C',
template: '<div>Here I am to save the day</div>'
}
}])
});
home.html
<div class="superman">This should be replaced</div>
home.html is a partial that's loaded into ng-view
Angular cannot load directives after it has been bootstrapped. My suggestion is:
Make myDirective.js do a define(), not a require()
Make sure myDirective.js is run before the require(['angular'],...) statement in config.js, e.g. do require(['angular','myDirective'],...). For this to work, myDirective should be shimmed to depend on angular - thanks # David Grinberg.
As a sidenote, take a look at this in Stackoverflow/this in GitHub, we have been trying to do RequireJS + Angular play together.

Resources