I have an app module defining dependencies (taken from phonecat-Tutorial) in the directory app:
app.module.js:
angular.module('phonecatApp', [
'phoneList' // (*)
]);
Then, in a directory app/phone-list are the module:
phone-list/phone-list.module.js:
angular.module('phoneList', []);
and component:
phone-list/phone-list.component.js:
angular.module('phoneList').component('phoneList', {...});
From registering the module phoneList in the first snippet at (*), how does AngularJS knows where to fetch the module from? Is the mapping from phoneList to phone-list-directory naming a builtin feature?
AngularJS has a dictionnary of modules. The key in this dictionnary is the string that you give your module when you register it with the following line :
angular.module('phoneList', []);
That's why the previous line must always have been executed in javascript before you can use your module by adding a component (like following line) :
angular.module('phoneList').component('phoneList', {...});
or by injecting your module into another module
angular.module('phonecatApp', [
'phoneList'
]);
The code for relevant modules has to be included in scripts included in the page. This is either done by manually adding various script tags or by task runners like grunt, gulp, webpack etc adding them for you.
If dependency module code doesn't exist angular will throw error
In simpler terms - where the code comes from is not angular's responsibility. It has to already exist for angular to work
I'd like to avoid the complex relative path issue described here by using one of the recommended solutions. I've come across three similar libraries:
rekuire
node-rfr aka Require from Root
requirish
I've tried all three and all are failing with "module not found" or a similar error which makes me believe I'm doing something fundamentally wrong. I'm relatively inexperienced with npm/node. I'm only using node in the browser using browserify to bundle my app into a single JS file.
Here's my extremely simple hello world example:
Structure:
lib/Bob.js
app.js
Bob.js
function Bob() {
return "I am bob";
}
module.exports = Bob;
app.js
var Bob = require('./lib/Bob.js');
console.log(Bob());
Bundling into a single JS:
browserify app.js -o bundle.js
Chrome's console successfully outputs "I am Bob".
Now if I try and of the libraries, let's say requirish:
REQUIRISH:
npm install requirish
app.js changes
'use strict';
require('requirish')._(module);
var Bob = require('lib/Bob');
console.log(Bob());
Bundling changes
browserify -t requirish app.js > bundle.js
I get the following error:
Error: Cannot find module '/lib/Bob' from '/Users/ngb/projects/MyApp/src/main/resources/public/js/hello'
at /Users/ngb/.nvm/v0.10.30/lib/node_modules/browserify/node_modules/resolve/lib/async.js:42:25
RFR:
'use strict';
var rfr = require('rfr');
var Bob = rfr('lib/Bob');
console.log(Bob());
Building
browserify app.js -o bundle.js -d
Chrome's console outputs the following error:
Uncaught Error: Cannot find module 'lib/Bob'
The Browserify can find module by parse string "require".
If you want to use both side client and server, use rfr for server side and browserify-rfr for browserify's transform.
In my opinion, the "rfr" is the best because this module does not override original require.
------- Notice! Additional Information,
As today browserify-rfr version leaves my local file path to bundle.js. This may cause another problem, so I chose requirish. Since the requirish changes behavior of original require by pushing a new path to module.paths, you always notice that and alert your coworker!
thanks!
https://www.npmjs.com/package/requirish
I am trying to minify and uglify my angularjs + typescript app using grunt-minified. Currently I am getting an error that my main module for the app is not available when I minify. I know why this is occuring due variable names no longer matching the names of the modules they reference. How would I set up annotation so angular is able to identify my main module after minification?
declare module BB {
}
module BB.MyModule {
// initialize the module
export var module = angular
// load the dependencies
.module("MyModule", [
// dependancies
]);
}
This basic setup is working fine unminified, but MyModule is not defined when I minify it. How would I go about defining for safe minification?
You have:
declare module BB {
}
Probably BB has been minified to something else. That would make module BB.MyModule be different from BB.
Solution: Your code is already safe for minification if the point where you bootstrap angular https://docs.angularjs.org/api/ng/function/angular.bootstrap is minified through the same pipeline as BB.module is passed through.
I am writing some extensions to lodash. The code related to this question can be download from here. The structure is that code is located in /shared/modules/myExtensions.js. Currently, my code is very basic and looks like this:
'use strict';
var _ = require('lodash');
_.mixin({
'myFunction' : function(s) {
return 'Hello ' + s;
}
});
module.exports = _;
My code will grow in complexity. For that reason, I want to setup unit tests from the start on this. Right now, my tests are located at /shared/tests/myExtensions.tests.js. That file looks like this:
'use strict';
describe('myModule', function() {
it('should work', function() {
expect(true).toBe(true);
});
});
This test always asserts to true. I'm trying to execute this Jasmine test via grunt. When I execute the this via Grunt, I get an error. The error confuses me because the grunt-jasmine-node module is defined in my package.json file. I've also checked that it got downloaded when I ran npm install. Either way, here is the error:
>> Local Npm module "grunt-jasmine-node" not found. Is it installed?
Running "jasmine:testShared" (jasmine) task
Testing jasmine specs via PhantomJS
>> Error: notloaded: Module name "../" has not been loaded yet for context: _. Use require([])
>> http://requirejs.org/docs/errors.html#notloaded at
>> ..\..\C:\Tests\jasmine\_SpecRunner.html:21
>> ..\..\C:\Tests\jasmine\.grunt\grunt-contrib-jasmine\require.js:12 v
>> ..\..\C:\Tests\jasmine\.grunt\grunt-contrib-jasmine\require.js:26 h
>> ..\..\C:\Tests\jasmine\.grunt\grunt-contrib-jasmine\require.js:31
>> ..\..\C:\Tests\jasmine\node_modules\glob\examples\g.js:1
>> Error: notloaded: Module name "../" has not been loaded yet for context: _. Use require([])
>> http://requirejs.org/docs/errors.html#notloaded at
>> ..\..\C:\Tests\jasmine\_SpecRunner.html:21
>> ..\..\C:\Tests\jasmine\.grunt\grunt-contrib-jasmine\require.js:12 v
>> ..\..\C:\Tests\jasmine\.grunt\grunt-contrib-jasmine\require.js:26 h
>> ..\..\C:\Tests\jasmine\.grunt\grunt-contrib-jasmine\require.js:31
>> ..\..\C:\Tests\jasmine\node_modules\glob\examples\usr-local.js:1
>> ReferenceError: Can't find variable: module at
>> ..\..\C:\Tests\jasmine\node_modules\glob\glob.js:37
>> Error caught from PhantomJS. More info can be found by opening the Spec Runner in a browser.
Warning: SyntaxError: Parse error Use --force to continue.
Aborted due to warnings.
This is so frustrating. My code can be downloaded from here. I've been working on this for 2 days now. If I don't get it done today, I'll have to go back to .NET. Can someone please help me get this resolved? I really want to keep moving in this direction. I believe this is just something really small.
grunt-jasmine-node is not defined in your package.json as Andy pointed out.
You can define and install it using the command npm-install --save grunt-jasmine-node that will fix that error.
This issue might be related https://github.com/gruntjs/grunt/issues/232.
Also you might want to seperate your dev dependencies and normal dependencies.
npm install --save-dev module includes the module in 'devDependencies' config, and
npm install --save module includes the module in dependencies config, in package.json.
I hope this will fix your problem, i am looking for that 500 bounty.
Edit
Edit:
Also it appears to me that you are mixing your client libraries with the server sides.
Namely you include vendor path like this:
File: tasks/options/jasmine.js
options: {
specs: "shared/tests/unit/**.tests.js",
// server libs
vendor: "node_modules/**/*.js",
// should be browser libs
// vendor: "shared/libs/lodash/dist/lodash.js",
}
All your node_modules folder gets included inside the browser.
Really what you should be doing is define your libraries in shared/libs
and use that path for the vendor option.
You can use bower to automatically install them.
And finally your actual code,
var _ = require('lodash');
_.mixin({
'myFunction' : function(s) {
return 'Hello ' + s;
}
});
module.exports = _;
This is again server side code, that gets loaded into the browser.
You should write this for the browser.
I am trying to get started with Karma tests, adding them to an existing Angular app.
This is my main app definition file:
angular
.module('myApp', [
'ngRoute',
'moduleAdherence'
]);
This is my controller file:
angular
.module('moduleAdherence', [])
.controller('AdherenceCtrl', ['$scope', function ($scope) {
$scope.awesomeThings = [1,2,3,4];
}]);
This is my first stab at a file:
describe('Controller: AdherenceCtrl', function () {
beforeEach(module('myApp'));
var MainCtrl,
scope;
beforeEach(inject(function ($controller, $rootScope) {
scope = $rootScope.$new();
MainCtrl = $controller('AdherenceCtrl', {
$scope: scope
});
}));
it('should attach a list of awesomeThings to the scope', function () {
expect(scope.awesomeThings.length).toBe(4);
});
});
When I try to run this with grunt test, it fails with the following error:
Uncaught Error: [$injector:nomod] Module 'd3' 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.
http://errors.angularjs.org/1.2.0/$injector/nomod?p0=d3
at /Users/me/Dropbox/projects/myapp/app/bower_components/angular/angular.js:1498
I don't understand this, because this controller does not Use D3. I do use D3 elsewhere in the app, in a directive, but I'm not registering it with the module (I use the external D3 file).
Why is Karma noticing D3? Shouldn't it be able to test this controller without D3?
In karma configuration file (karma.conf.js) you need to define all libraries.
etc.
// list of files / patterns to load in the browser
files: [
'app/lib/angular/angular.js',
'app/lib/angular-route/angular-route.js',
'test/lib/angular-mocks.js',
'app/app.js',
'app/controllers/*.js',
'app/services/*.js',
'app/*',
'test/spec/**/*.js'
],
Had a similar problem and my solution (inspired someway by #danba comment) was to load the scripts in the files in the exact same order as they were loaded in the index.html.
In my case globbing patterns like app/scripts/**/*.js were causing trouble to karma which constantly threw errors.
Maybe not the most elegant solution to copy all the scripts definitions but worked in the end so my test could finally get back running. Hope it helps.
EDIT: Editing this because today I probably (and hopefully) got the hang of what was going wrong here. So it seems that Karma does not like globbing patterns when the same module is defined in one file and used in many different files. Let's say that your folder structure is like this:
Suppose that in AuthService.js you have your module definition for all your services in that folder, so that that file starts with:
angular.module('myApp.services', [
'myApp.urls',
'ngCookies'
])
Then in all the other files you're just attaching other services to that same module. In the picture tokenService.js would start with:
angular.module('myApp.services');
If everything stays this way everything will probably work. But if by any chance I define the module the other way round, so the module definition is not anymore in the first file of that folder but on another that Karma reads after AuthService then it will throw an error and refuse to complete the tests.
Solution 1
A solution might be to put the module definition in its own file, starting with an underscore. Finally, let all the siblings files depend on that one(s). So the above folder structure should be:
Solution 2
Another - probably better - solution is to mark the files where the modules are defined with a common suffix/extension for example service.module.js while the files that depend on it could be named normally like authService.js, tokenService.js.
The Karma configuration at that point will become something like:
// list of files / patterns to load in the browser
files: [
'app/lib/angular/angular.js',
'test/lib/angular-mocks.js',
'app/app.js',
'app/**/*.module.js', // <-- first the module definitions...
'app/**/*.js', // <-- ..then all the other files
'test/spec/**/*.js'
],
This way karma will load the modules definitions first and then those file that depend on them.
I also had the same issue, in my case problem occured because there were several files per module which is a bad practice since we can point to not initialized module. Solved this by including just one file per module.
Always load the non minified version of angular into karma.
it will display errors and help you better to find out what to change.
In your case, it's the order of the files being loaded by karma.
Check your index.html that you don't include something by a script tag like.
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5angular-resource.js"
All your Javascript file need to be in your karma.config.js
Here's a simple solution that worked for me, based on above Solution #1 by #Nobita, AND #danba's comment.
In karma.conf.js, explicitly load the prerequisite file above the pattern that pulls in the rest:
files: [
...
'app/module.js',
'app/*.js'
]
Karma does not seem to mind that the pattern also matches 'module.js'.