I recently brought this angular library to my project:
https://github.com/a5hik/angular-multi-select-tree
Everything works great with it besides my unit testing. I am getting this error when running my tests:
Module 'multi-select-tree' 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.
Which puzzles me as I have added it to my chutzpah.json references (and confirmed the paths are correct many times) like so:
{ "Path": "../Scripts/Lib/ng-multi-select-tree/ng-multi-select-tree.js" },
{ "Path": "../Scripts/Lib/ng-multi-select-tree/ng-multi-select-tree.tpl.js" },
And have included it in my main app.js file. The commented out code allows for Chutzpah to find the library, however this breaks all functionality of it:
// work around for Chutzpah test discovery
//angular.module('multi-select-tree', []);
var authoring = angular.module('authoring', ['ms-content', 'portalCommon', 'ngFileUpload', 'ckeditor', 'ui.bootstrap', 'AdalAngular', 'ui.sortable', 'nvd3', 'multi-select-tree']).run(['$rootScope', function ($rootScope) {}]);
The thing I am noticing is how this library instantiates the module like so:
(function () {
'use strict';
var mainModule = angular.module('multi-select-tree');
They seem to instantiate the module and then set it to a variable. Coworkers of mine are implying that this may be the problem. Any ideas as to why Chutzpah is having a hard time finding this particular module?
This ended up having nothing to do with how my module was initialized. It turns out Chutzpah does like lambdas ('=>').
Related
Hi I have a problem :) I developed an angular project and it works fine in my localhost apache. I'm using angular 1.4.3 for frontend things and node.js for backend things. Now I need to use Grunt to version it.
I did many config (such as that maple thing disabled.it changes all variables names such as a,b,c from indexCounter,PersonCounter,AgencyCounter and it causes some problems.) But I get an error everytime I try to run. It is like [module] cannot found. My project works on my local machine If I dont grunt it but after the grunt I take 3 files as vendor.js vendor2.js and app.js. In vendor.js I have native angular js files. In vendor2.js I have plugins. and lastly In app.js I have controllers. I'm added them in my index HTML in this order;
vendor.js
vendor2.js
app.js
Do you have any idea about that?
Problem: In angular you cannot minify your code without using either .$inject or array syntax.
Solution
For each controller, directive, service etc. that you add to your module, you will have to add en extra array of strings specifying the dependencies that should be injected into you service, controller etc.
Example
Using $inject property
function mainController(indexCounter,PersonCounter,AgencyCounter) {
//Controller implementation
}
mainController.$inject=['indexCounter','PersonCounter','AgencyCounter'];
angular
.module('mymodule')
.controller('mainController', mainController);
Using array
var mainController;
function controller(indexCounter,PersonCounter,AgencyCounter) {
//Controller implementation
}
mainController=['indexCounter','PersonCounter','AgencyCounter', controller];
angular
.module('mymodule')
.controller('mainController', mainController);
When you don't specify the dependecies in an array, angular will try to find an registered dependency based on its' parameter name. e.g. function mainController(indexCounter) {}, then angular will try to find a registered dependency called indexCounter. It works perfectly fine when the code is not minified. However, when minified the indexCounter parameter name will be changed to a shorter name, e.g. a. And when trying to find dependency a which is not registered in your app. It's gonna fail to instaciate your angular module.
I am working on a project with specific authentification that is already working in Ionic. I have to implement the same for the admin panel that will be available only for web devices, so I already installed all the dependencies, configured the app and did already the HTML/CSS stuff in ZURB Foundation for Apps 1.1.
Now I am stuck on the implementation of the controllers and services.
I read the official documentation and there is not much explanation for the custom controllers and services, so I found few texts on the web that explain the structure of the Foundation for Apps. I found also a sample app with the structure that is explained here: ORGANIZING ANGULAR FILES IN ZURB FOUNDATION FOR APPS and copied the sample files for each page from here: Foundation for Apps Template
So I put inside my app the About, Contact, Home and Shared folders inside the assets/js folder.
So the Shared folder for example contains controllers.js file with the following code:
(function () {
'use strict';
var controllers;
AppCtrl.$inject = ['$scope'];
function AppCtrl($scope) {
// This is a shared controller because its the application parent controller
}
controllers = {
AppCtrl: AppCtrl
};
angular.module('SharedModule').controller(controllers);
})
The module.js file contains this:
(function () {
'use strict';
angular.module('SharedModule', [ /* Dependencies to be shared everywhere */ ]);
})
The app.js file has the almost the same code as the generated file, except the custom modules are specified:
(function() {
'use strict';
angular.module('application', [
'ui.router',
'ngAnimate',
//foundation
'foundation',
'foundation.dynamicRouting',
'foundation.dynamicRouting.animations',
// My modules
'SharedModule',
'ContactModule',
'AboutModule',
'HomeModule'
])
.config(config)
.run(run)
;
config.$inject = ['$urlRouterProvider', '$locationProvider'];
function config($urlProvider, $locationProvider) {
$urlProvider.otherwise('/');
$locationProvider.html5Mode({
enabled:false,
requireBase: false
});
$locationProvider.hashPrefix('!');
}
function run() {
FastClick.attach(document.body);
}
})();
So now, when I run the application I get the following error:
Uncaught Error: [$injector:modulerr] Failed to instantiate module
application due to: Error: [$injector:modulerr] Failed to instantiate
module HomeModule due to: Error: [$injector:nomod] Module 'HomeModule'
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.
Any help would be appreciated, thanks.
I fixed the problem.
I tried to remove the modules one by one to test if there is a problem with individual modules, but the same error was thrown, so I checked the individual files as well, but the files look the same as in the sample app. Then, I checked if the dependencies are called, but since they are not called inside the index file like in a regular AngularJS app, I compared the gulpfile.js and came with the solution:
Inside the appJS array I had to include the paths for the .js files, so that part of the gulpfile.js looks like this now:
appJS: [
'client/assets/js/app.js',
// Load my modules
'client/assets/js/*/module.js',
'client/assets/js/*/controllers.js',
'client/assets/js/*/factories.js',
'client/assets/js/*/services.js',
'client/assets/js/*/directives.js'
]
I'm working in a project with angular and browserify, this is the first time for me to use this two tools together, so I would like some advice on which is the way to require files with browserify.
We may import those files in different ways, Until now I experimented this way:
Angular App:
app
_follow
- followController.js
- followDirective.js
- followService.js
- require.js
- app.js
For each folder with in the files for a plugin I created an require.js file and in it I require all the files of that folder. Like so:
var mnm = require('angular').module('mnm');
mnm.factory('FollowService', ['Restangular',require('./followService')]);
mnm.controller('FollowController',['$scope','FollowService',require('./followController')])
mnm.directive('mnmFollowers', ['FollowService',require('./followDirective')]);
and then require all require.js files in a unique file called app.js that will generate the bundle.js
Question:
This way to require the files can be a good structure, or it will have some problem when I need to test? I would like to see your way to achieve good structure with angular and browserify
AngularJS and browserify aren't, sadly, a great match. Certainly not like React and browserify, but I digress.
What has worked for me is having each file as an AngularJS module (because each file is already a CommonJS module) and having the files export their AngularJS module name.
So your example would look like this:
app/
app.js
follow/
controllers.js
directives.js
services.js
index.js
The app.js would look something like this:
var angular = require('angular');
var app = angular.module('mnm', [
require('./follow')
]);
// more code here
angular.bootstrap(document.body, ['mnm']);
The follow/index.js would look something like this:
var angular = require('angular');
var app = angular.module('mnm.follow', [
require('./controllers'),
require('./directives'),
require('./services')
]);
module.exports = app.name;
The follow/controllers.js would look something like this:
var angular = require('angular');
var app = angular.module('mnm.follow.controllers', [
require('./services'), // internal dependency
'ui.router' // external dependency from earlier require or <script/>
// more dependencies ...
]);
app.controller('FollowController', ['$scope', 'FollowService', function ...]);
// more code here
module.exports = app.name;
And so on.
The advantage of this approach is that you keep your dependencies as explicit as possible (i.e. inside the CommonJS module that actually needs them) and the one-to-one mapping between CommonJS module paths and AngularJS module names prevents nasty surprises.
The most obvious problem with your approach is that you're keeping the actual dependencies that will be injected separate from the function that expects them, so if a function's dependencies change, you have to touch two files instead of one. This is a code smell (i.e. a bad thing).
For testability either approach should work as Angular's module system is essentially a giant blob and importing two modules that both define the same name will override each other.
EDIT (two years later): Some other people (both here and elsewhere) have suggested alternative approaches so I should probably address them and what the trade-offs are:
Have one global AngularJS module for your entire app and just do requires for side-effects (i.e. don't have the sub-modules export anything but manipulate the global angular object).
This seems to be the most common solution but kind of flies in the face of having modules at all. This seems to be the most pragmatic approach however and if you're using AngularJS you're already polluting globals so I guess having purely side-effect based modules is the least of your architectural problems.
Concatenate your AngularJS app code before passing it to Browserify.
This is the most literal solution to "let's combine AngularJS and Browserify". It's a valid approach if you're starting from the traditional "just blindly concatenate your app files" position of AngularJS and want to add Browserify for third-party libs, so I guess that makes it valid.
As far as your app structure goes this doesn't really improve anything by adding Browserify, though.
Like 1 but with each index.js defining its own AngularJS sub-module.
This is the boilerplate approach suggested by Brian Ogden. This suffers from all the drawbacks of 1 but creates some semblance of hierarchy within AngularJS in that at least you have more than one AngularJS module and the AngularJS module names actually correspond to your directory structure.
However the major drawback is that you now have two sets of namespaces to worry about (your actual modules and your AngularJS modules) but nothing enforcing consistency between them. Not only do you have to remember to import the right modules (which again purely rely on side-effects) but you also have to remember to add them to all the right lists and add the same boilerplate to every new file. This makes refactoring incredibly unwieldy and makes this the worst option in my opinion.
If I had to chose today, I would go with 2 because it gives up all pretense of AngularJS and Browserify being able to be unified and just leaves both to do their own thing. Plus if you already have an AngularJS build system it literally just means adding an extra step for Browserify.
If you're not inheriting an AngularJS code base and want to know which approach works best for starting a new project instead: don't start a new project in AngularJS. Either pick Angular2 which supports a real module system out of the box, or switch to React or Ember which don't suffer from this problem.
I was trying to use browserify with Angular but found it got a bit messy. I didn't like the pattern of creating a named service / controller then requiring it from another location, e.g.
angular.module('myApp').controller('charts', require('./charts'));
The controller name / definition is in one file, but the function itself is in another. Also having lots of index.js files makes it really confusing if you lots of files open in an IDE.
So I put together this gulp plugin, gulp-require-angular which allows you write Angular using standard Angular syntax, all js files which contain angular modules and dependencies of angular modules which appear in your main module dependency tree are require()'d into a generated entry file, which you then use as your browserify entry file.
You can still use require() within your code base to pull in external libraries (e.g lodash) into services / filters / directives as needed.
Here's the latest Angular seed forked and updated to use gulp-require-angular.
I've used a hybrid approach much like pluma. I created ng-modules like so:
var name = 'app.core'
angular.module(name, [])
.service('srvc', ['$rootScope', '$http', require( './path/to/srvc' ))
.service('srvc2', ['$rootScope', '$http', require( './path/to/srvc2' ))
.config...
.etc
module.exports = name
I think the difference is that I don't define individual ng-modules as dependencies to the main ng-module, in this case I wouldn't define a Service as an ng-module and then list it as a dep of the app.core ng-module. I try to keep it as flat as possible:
//srvc.js - see below
module.exports = function( $rootScope, $http )
{
var api = {};
api.getAppData = function(){ ... }
api.doSomething = function(){ ... }
return api;
}
Regarding the comment of code-smell, I disagree. While it's an extra step, it allows for some great configurability in terms of testing against mock-services. For instance I use this quite a bit for testing agains services that might not have an existing server-API ready:
angular.module(name, [])
// .service('srvc', ['$rootScope', '$http', require( './path/to/srvc' ))
.service('srvc', ['$rootScope', '$http', require( './path/to/mockSrvc' ))
So any controller or object dependent on srvc doesn't know which it is getting. I could see this getting a bit convoluted in terms of services being dependent on other services, but that to me is bad design. I prefer to use ng's event system to communicate betw. services so that you keep their coupling down.
Alan Plum's answer is just not a great answer or at least not a great demonstration of CommonJS modules and Browserify with Angular. The claim that Browserify does not mix well with Angular, compared to React is just not true.
Browserify and a CommonJS module pattern work great with Angular, allowing you to organize by features instead of types, keep vars out of global scope and share Angular Modules across apps easily. Not to mention you do not need to ever add a single <script> to your HTML ever again thanks to Browserify finding all your dependencies.
What is particular flawed in Alan Plum's answer is not letting requires in each index.js for each folder dictate dependencies for Angular modules, controllers, services, configurations, routes etc. There is no need for a single require in the Angular.module instantiation, nor a single module.exports as in the context that Alan Plum's answer suggests.
See here for a better module pattern for Angular using Browserify: https://github.com/Sweetog/yet-another-angular-boilerplate
Sorry for the awkward post title but it's a very weird situation to be in. In my project I have a folder structure like so:
/filters
index.js
[...]
/controllers
index.js
[...]
app.js
app.js is basically the entry point of my application and I thought it would be cool if I could automatically load the contents of those directories by require()ing the directory and having index.js in each of those directories take care of loading whatever it needs to load.
But I'm running into a problem I don't understand. Because I'm being intentionally obtuse (this is a learning/experimentation exercise) I decided to try and keep it as DRY as humanly possible so I tried this big of code to handle the module loading:
'use strict';
var customModules = [
'controllers',
'filters'
];
//require('./controllers');
//require('./filters');
for (var i in customModules) {
if (customModules.hasOwnProperty(i)) {
require('./' + customModules[i]);
}
}
var nativeModules = [
'ngSanitize'
];
angular.module('app', customModules.concat(nativeModules));
I'm planning on extracting that to it's own module but it'll do for demonstration. For some reason this code throws this exception:
Uncaught Error: Cannot find module './controllers'
But when I load it using a static string
require('./controllers');
No problems, everything works and my sample application behaves as expected.
Checkout the Browserify Handbook at how browserify works (emphasis mine):
Browserify starts at the entry point files that you give it and searches for any require() calls it finds using static analysis of the source code's abstract syntax tree.
For every require() call with a string in it, browserify resolves those module strings to file paths and then searches those file paths for require() calls recursively until the entire dependency graph is visited.
Bottom line: the dependencies must be statically declared; your code involving the dynamcally-created require() calls cannot work (although a good idea in principle).
You could achieve a similar result using server-side or build-time techniques.
In order to share AMD modules between the browser and node, I'm using RequireJS in both places (see RequireJS in Node).
server/dataDao.js:
var requirejs = require('requirejs');
var dataDao = module.exports = {};
requirejs(['client/resource'], function (Resource) {
...
});
client/resource.js:
define(['underscore'], function (_) {
...
});
This has generally been working ok, as long as the shared module does not involve any dependencies that don't work on the server.
I would like to introduce use.js, however, to avoid manually wrapping non-AMD compatible libs like underscore. To do so, I have to prefix listed dependencies with use! (to trigger the use plugin in RequireJS).
client/resource.js:
define(['use!underscore'], function (_) {
...
});
This works well in the browser, but causes errors in Node:
Error: Calling node's require("use") failed with error: Error: Cannot find module 'use'
I believe this is not specific to the use plugin, but also text etc.
Has anyone else encountered this problem?
With version 0.3 of use I was able to get it working in node. Per the comment on your question, it may be a configuration issue -- it took me a couple of tries to get the pathing right.