AngularJS and RequireJS: No module: myApp - angularjs

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']);
});
});

Related

Unknown provider: uibCarouselProvider when trying to change it's template

I am trying to get angularjs to play nicely with local templates that override bootstrap ones.
I had initially use the same file path (uib/template/carousel/carousel.html for example) which is fine when published, but locally it doesn't work.
So, I found this soluton:
Angular ui bootstrap directive template missing
They have said you can override the template with a new url with the $provide service.
So I have done this:
'use strict';
angular.module('core').config(coreConfig);
function coreConfig($provide) {
$provide.decorator('uibCarousel', function ($delegate) {
console.log($delegate[0]);
$delegate[0].templateUrl = 'bootstrap/carousel/carousel.html';
return $delegate;
});
};
which should work.
my core module looks like this:
'use strict';
angular.module('core', [
'ngCookies',
'ngNotify',
'ngResource',
'ngSimpleCache',
'ui.bootstrap',
'ui.bootstrap.tpls',
'ui.router',
'ui.select',
// -- remove for brevity -- //
]);
As you can see, I have the ui.bootstrap.tpls module loaded, so in theory, my code should work.
Can anyone think of a reason that it won't?
Sorry for all the comment spam. I think I have found the answer to your issue.
You must append Directive to a directive when defining the decorator:
function coreConfig($provide) {
$provide.decorator('uibCarouselDirective', function ($delegate) {
console.log($delegate[0]);
$delegate[0].templateUrl = 'bootstrap/carousel/carousel.html';
return $delegate;
});
};
From the docs:
Decorators have different rules for different services. This is
because services are registered in different ways. Services are
selected by name, however filters and directives are selected by
appending "Filter" or "Directive" to the end of the name. The
$delegate provided is dictated by the type of service.
https://docs.angularjs.org/guide/decorators
This is an example from my own (working) code:
$provide.decorator("uibDatepickerPopupDirective", [
"$delegate",
function($delegate) {
var directive = $delegate[0];
// removed for brevity
return $delegate;
}
]);

unable to init ocLazyLoad error while including dependency inside a lazyloaded module

I am trying to load modules progressively. I made a file ‘lazyModule.js’ and I load this module using oclazyLoad. When I define myModule.js dependency in this lazyModule.js, it throws following error on console:
No module found during bootstrap, unable to init ocLazyLoad. You should always use the ng-app directive or angular.boostrap when you
use ocLazyLoad.
lazyModule.js
define([
'angular',
'components/infrastructure/myModule'
], function(angular) {
'use strict';
return angular.module('lazyModule',
[
'myModule'
]);
});
myModule.js
define([
'angular',
'ui-bootstrap',
'ocLazyLoad'
], function initModule(angular) {
'use strict';
angular.module('html.myModule', [ 'oc.lazyLoad']);
});
This is how i am lazy loading lazyModule.js:
initializeLazyModule: function(scope) {
var template;
try{
// checking for existing module
angular.module('lazyModule');
isLoaded=true;
}catch(err) {
isLoaded=false;
}
if (!isLoaded) {
return require(['apps/controlCenter/lazyModule'], function() {
$ocLazyLoad.inject('lazyModule');
ControlCenterUtilities.checkAndApplyScope(scope);
$compile($('#my-module'))(scope);
});
}
else {
return;
}
}
Although, when I remove the dependency for oc.lazyLoad module from myModule.js, the console error goes away.
But i do not have option to remove oc.lazyload module dependency from myModule, since it will break for some other component which is consuming my module directly without having loaded oclazyload already.
Its basically happening because oc.lazyload module is being injected twice.
Please help
I have found solution to this.
oc.lazyLoad should not be included in the angular dependency of new angular module creation, if oc.lazyLoad is already loaded through bootstrap angular module.
oc.lazyLoad tries to initialize itself whenever it is included in the new module dependency.
lazyModule.js
define([
'angular',
'components/infrastructure/myModule'
], function(angular) {
'use strict';
var dependentModules = [
try {
angular.module('oc.lazyLoad');
} catch (moduleError) {
dependentModules.push('oc.lazyLoad');
}
return angular.module('lazyModule', dependentModules);
});

What gulp-angular-filesort really does for gulp-inject?

Can anybody show an example of what gulp-angular-filesort really does and how to use it properly?
The thing is that I’ve recently realized that my gulp-angular-filesort doesn’t sort angularjs files at all, however my AngularJS App with lots of files works fine.
So, I’ve come up with two questions:
Is AngualarJs still sensitive for source files order? As to me, it looks like it isn’t.
What gulp-angular-filesort actually does? I can’t see any results of its work.
I’ve thought that gulp-angular-filesort looks at angular.module statements and sort files according to specified dependency in the brackets. It looks like I was wrong.
Please look at my sample below.
// File: Gulpfile.js
'use strict';
var
gulp = require('gulp'),
connect = require('gulp-connect'),
angularFilesort = require('gulp-angular-filesort'),
inject = require('gulp-inject');
gulp.task('default', function () {
gulp.src('app/index.html')
.pipe(inject(
gulp.src(['app/js/**/*.js']).pipe(angularFilesort()),
{
addRootSlash: false,
ignorePath: 'app'
}
))
.pipe(gulp.dest('app'))
;
connect.server({
root: 'app',
port: 8081,
livereload: true
});
});
//a_services.js
'use strict';
angular.module('myServices', [])
.factory('MyService', function () {
return {
myVar:1
};
})
;
//b_controllers.js
'use strict';
angular.module('myControllers', ['myServices'])
.controller('MyController', function ($scope, MyService) {
$scope.myVar = MyService.myVar;
})
;
// c_app.js
'use strict';
angular.module('myApp', ['myControllers']);
The result of gulp-inject is the following:
<!-- inject:js -->
<script src="js/c_app.js"></script>
<script src="js/b_controllers.js"></script>
<script src="js/a_services.js"></script>
<!-- endinject -->
I was expected exactly an opposite order to make the App work (however it still does work).
So, using of gulp-angular-filesort simply sorted files alphabetically, despite of all the dependencies specified in the angular.module(...,[...])
What is going on here?
Actually in your case you don't need gulp-angular-filesort because you declare a module for each file. The dependency injection mechanism for angular will figure out the correct way to call your modules according to your dependencies.
You'll need gulp-angular-filesort only when you have one module spread across multiple files. So for your example if all files use 'myApp' as the module name. Then the plugin will sort the files correctly: always the one with dependencies before the others.
Here your example modified so that gulp-angular-filesort is needed:
//a_services.js
'use strict';
angular.module('myApp')
.factory('MyService', function () {
return {
myVar:1
};
})
;
//b_controllers.js
'use strict';
angular.module('myApp')
.controller('MyController', function ($scope, MyService) {
$scope.myVar = MyService.myVar;
})
;
// c_app.js
'use strict';
angular.module('myApp', []);
In this case this will still be:
c_app.js
b_controller.js
a_service.js
gulp-angular-filesort moves files containing module’s declaration above the files wherein the modules are mentioned.
If the module is mentioned before it declared, you’ll got errors like these:
"angular.js:68 Uncaught Error: [$injector:nomod] Module 'myApp' 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."
"angular.js:13294 Error: [ng:areq] Argument 'MyController' is not a function, got undefined"

Encountering strictdi error for a controller where $inject is being used

I have enabled strict-di on my application as I am trying to prepare my source code for minification and am now working through resolving strictdi errors being thrown.
I have the following controller thats throwing a strictdi error, but I am correctly annotating using $inject (I am using the John Papa style guide too) and I cannot figure out where I am going wrong:
(function () {
'use strict';
angular
.module('app.products')
.controller('ProductsPageController', Controller);
Controller.$inject = ['MyToolbarService'];
function Controller(MyToolbarService) {
MyToolbarService.getToolbar('main').then(function (toolbar) {
toolbar.setTitle('GENERAL_TERMS.PRODUCTS');
});
}
})();
Error: [$injector:strictdi] ProductsPageController is not using
explicit annotation and cannot be invoked in strict mode
I have another controller (below) that works in exactly the same manner, and when the view loads that this is bound, no error is thrown and my toolbar service is setting its title:
(function () {
'use strict';
angular
.module('app.home')
.controller('HomePageController', Controller);
Controller.$inject = ['MyToolbarService'];
function Controller(MyToolbarService) {
MyToolbarService.getToolbar('main').then(function (toolbar) {
toolbar.setTitle('GENERAL_TERMS.WELCOME_MESSAGE');
});
}
})();
Banging my head against the wall now! Anyone got any suggestions?
Thanks
I typically don't write my DI in this fashion, most of the time I pass the array as the second argument to the .controller() function.
As to why you are having issues I am not sure. Could it be indentation? (crazy as it seems).
If you wanted to rule anything out I suppose you could try and write it:
(function () {
'use strict';
angular
.module('app.home')
.controller('HomePageController', ['MyToolbarService', Controller]);
function Controller(MyToolbarService) {
MyToolbarService.getToolbar('main').then(function (toolbar) {
toolbar.setTitle('GENERAL_TERMS.WELCOME_MESSAGE');
});
}
})();

Angular ui calendar will not load from injected controller

I'm using AngularJS and requireJS and I'm using this seed template to help me to get Angular to place nicely with requireJS which can be found here LINK
At the moment I'm trying to integrate AngularUI's calendar into the project but I keep recieving the error "Cannot call method 'map' of undefined" when the calendar code is in calendarCtrl.js with the scope injected into this controller. However when I place the code directly in the controller (controllers.js) the calendar works.
Plunkr link: LINK
In angular the internal injectors for all of the scope controls are initialized by the app. You managed to detach your app from your controller definition so angular didn't know how to inject the pieces needed for the use of the $scope object.
Option 1
So to get this to work so you need to either define an app/module that get's passed into the space where the control is defined:
define(['angular'], function (angular) {
'use strict';
return angular.module('TP.controllers', []);
});
calendar control:
define([
"jquery",
"controllers",
"jqueryui",
"full_calendar",
"calendar",
],
function($, controllers) {
return controllers
.controller('calendarCtrl', ['$scope', function($scope) {
....
In which case you'd have to include every individual controller in your top level application like:
define([
'angular',
'controllers',
'calendarCtrl',
'full_calendar',
'calendar'
], function (angular, controllers) {
'use strict';
return angular.module('TP', ['TP.controllers', 'ui.calendar']);
});
Which to some degree defeats the purpose of using AMD.
Option 2
A better option is to define your calendar as it's own module then define it as a child of controllers. This maintains the angular injection chain so the scope has the proper context when initializing the calendar actions.
Defining the controllers root:
define(['angular', 'calendarCtrl'], function (angular) {
'use strict';
return angular.module('TP.controllers', ['calendarCtrl']);
});
Defining the calendar controller:
define([
"jquery",
"angular",
"jqueryui",
"full_calendar",
"calendar",
],
function($, angular) {
return angular.module('calendarCtrl', [])
.controller('calendarCtrl', ['$scope', function($scope) {
...
Working plunker of this version at http://plnkr.co/edit/Xo41pqEdmB9uCUsEEzHe?p=preview.

Resources