Do you guys know if it's possible to add a module dependency after it's been created? Something like that:
// init module in file A
angular.module("myApp", []);
// retrieve module in file B and add new dependencies:
mod = angular.module("myApp");
// now I want to add an 'ngResource' dependency to mod
// ???
EDIT: I understand this may seem a weird question. I am working on a component based app organization and want too see if a subcomponent can add dependencies to it parent component module without defining its own module. Something like that:
app/
components/
|__componentA/
|__app.js // initializes component A module
|__subcomponentA/
|__app.js // want to add subcomponentA dependencies to componentA module from here
My alternative is simply declare all subcomponentA dependencies directly on the componentA module, but from organization point of view, I'd prefer to keep these dependencies inside the subcomponentA directory, so if I later decide to remove the subcomponentA from the app, I don't need to remember to remove its dependencies from the componentA module. I want everything that concerns subcomponentA to be grouped inside the subcomponentA directory. My build script will ensure that componentA code is processed before the subcomponetA is, though.
Thank you to everyone who takes a stab at this.
I use the following method for this and working fine for me.
var app = angular.module("myApp", []);
angular.module("myApp").requires.push('ngResource');
I don't think this is possible. However, I'd love to be proven wrong.
From my experience (and according to the Angular documentation) module dependencies can only be declared when initializing a module. It's worth noting that until the application is bootstrapped, the dependencies aren't completely set. It's not possible to add dependencies to a running application as far as I know, unless there's a way to rebootstrap the entire app, which might have unwanted side effects anyway.
Edit: Actually....I've never tried this, but this actually might be a lot simpler than I originally thought. We could try the following:
File A:
window.myApp_dependencies = []; // Add dependencies to the global scope.
angular.module('myApp', dependencies);
File B:
var mod = angular.module("myApp");
window.myApp_dependencies.push('ngRoute');
This isn't really ideal as you are forced to create a variable on the global scope. It would be possible to do it with modules, though. Note that in this case, the dependencies would only be mutable until the app actually started - so, you could split dependencies across files, but you wouldn't be able to change them at runtime.
I don't know if this works. I'm going to try it out tomorrow, though.
Strange question but still what you trying to achieve is something wrong in prospect of angularjs/SPA/dependency injection
Your use case is something like you wants to use this dependency in a particular module or in one page. Thats why you wants to inject it at one position not the other.
But, doing this would make two different scopes for your application becuase using same name of module if you reinitiallized that module that would be different that the other one which is already declared
say: file A
angular.module("myApp", []);
This is defined and in file B
mod = angular.module("myApp", ['ngResource']);
so this would cause to have two different app with same name in one application and that two app with same name in different files
so its something like to have two different angular module inside on application.
Second option: let have the same module across the application and inject in at one point and in any controller you wants to use this inject that as a argument in that controller.
Hope this help!
Related
AngularJs provides you the possibility to create modules. All fine. It also give you the power to add components to your modules like service, controller, etc...
My only problem with that is that no matter in what module did you define a component, from another module it can be entirely overwritten.
Examples:
app.module('aModule').controller('SimpleController', functino(){...});
app.module('bModule').controller('SimpleController', functino(){...});
If you try to define let's say a state definiction with ui-router, it will just won't work well, since one controller will completely overwrite the one loaded first.
Did you guys met with this problem too or it's just me?
no, that's normal behavior. You can namespace it like 'component.controller' (so do this in the name of the controller, not the module) which helps, other then that is not possible in Angular 1
I am having problem while using Require.js to load dependencies for my module. Basically I have following module in which I define extension of Backbone Model.
define(["models/services/ProjectServices"],
function (ProjectServices) {
var SomeModel = Backbone.Model.extend({
sample: function () {
var servicesFromDependency = ProjectServices; //undefined
var projectServices = window.require.s.contexts._.defined["models/services/ProjectServices"]; //defined and Ok
}
});
return SomeModel;
}
);
In this module I want to use already defined ProjectServices module. In order to do that I add it as a dependency. The thing is that within defined sample function ProjectServices is showing as undefined. But if I look directly into require defined modules it is showing there correctly and I can use it (although I do not want as I don't like to hack it this way). To add more context, I am also using this ProjectServices dependency on other module and there it is loaded properly through define function.
Any suggestions on why module would not be loaded?
Try this inside a module:
var ProjectServices = require('models/services/ProjectServices');
I think in many situations, there is no need for window global assignment and I try to avoid while using requirjs.
The only thing I can come up with is a possible circular reference, meaning that two modules require each other (which should not be the case).
As you say that the require works well in other modules, it should not be due to a missing return statement in the required module, or a wrong path. (You might check this anyway).
I started learning angularjs and I see 2 types of module uses and I cant understand when to use this and when this:
example1:
var app = angular.module('app', []);
app.factory('Comment', function($http) {
}
app.controller('mainController', function($scope, $http, Comment) {
}
or
example2:
angular.module('commentService', [])
.factory('Comment', function($http) {
}
angular.module('mainCtrl', [])
.controller('mainController', function($scope, $http, Comment) {
}
var app = angular.module('app', ['commentService','mainCtrl']);
sometimes I see module declarion in each file(services factory controllers and so on)
and sometimes I see using the app module in those files, what is the right way? and why both of them works?
First and foremost, if you're concerned about app organization, read the discussion on the yeoman-generator-angular issue board from about a year ago. There's way more wisdom there than you could feasibly expect to get in a SO answer.That said, I'll try to provide an answer that's more pertinent to your specific concern, and (marginally) more concise.
DO NOT make a module for a single controller like angular.module('MainCtrl',[]).controller('MainCtrl'), or even a set of controllers who are only related in that they are all controllers:
angular.module('appCtrl', [])
.controller('appleController', function ($scope) {})
.controller('orangeController', function ($scope) {})
.controller('unicornController', function ($scope) {})
;
Why is this a bad idea? First, by definition, it's categorical, not modular; modules are groupings of system components which are related topically, not conceptually. When you're building a car, you don't put in all of the nuts and bolts at once. You put in the nuts and bolts that hold together the module that you're building. Controllers are like nuts and bolts. An engine is like a module.
Second, now you have to inject the appCtrl module anywhere that you want access to a controller. That's just a mess for developers to have to deal with; they're always digging through the code trying to find "whatever that module with that one thing in it" was, or they'll just repeat code all over the place.
Dependency Injection in AngularJS is less a rule than a (clever and awesome) string manipulation hack, and JavaScript has no "namespacing" system in the classical sense. Creating modules like app.products or app.cart is more for the developer's convenience and/or controlling the release cycle than making the program "work".
For these and other reasons, I caution developers against "Premature Modularization". If you're writing something app-specific---that is, you won't be reusing it right now in another app---why not just attach it to your app module? Then you have access to it anywhere in your app that you want it. (There are of course complexities that might cause you to change this, but if/when those do arise that's when you modularize).
Structure your directories by feature (Angular conventions do condone BDD, after all):
|-app/
|-|-cart/
|-|-|-CartItemsModel.js
|-|-|-OrderRepository.js
|-|-|-cart.html
|-|-|-add-item-modal/
|-##some more cart stuff
|-|-checkout/
|-|-|-confirmation/
|-|-|-|-confirmation.html
|-|-|-|-confirmation.less
If you're writing feature files or getting acceptance criteria from your employer, you can even model your directory structure directly after those features or requirement sets. That makes everything smooth from defining the scope of an iteration through documentation through revisiting code at a later time.
Both example work. But for instance with the example 2, this syntax can be used for separation of concern. You may need a module that is responsible for providing services which gives you function for Rest calls. Or another module that package some directives.
It's generally considered good practice to segregate your modules into different files. This will ensure that you are practicing good code control, and gives your code a greater degree of portability and debug-ability. Instead of declaring modules in the same file, declare them in different files with their module name.
It's good practice to segregate your files based on their module-controller relationship -- that is, each controller should have its own file, like this:
\scripts\controllers\
- - main.js
- - comments.js
Then, inside your main.js file, you'll start off with the controller declaration:
//main.js
angular.module('app')
.controller('MainController', function ($scope, $http) {
// Controller-scope stuff here
});
Finally, inside your comments.js file:
angular.module('app')
.controller('CommentsController', function($scope, $http, $routeParams) {
// Comment controller code
});
One way to help with organization right off the bat is to organize your files is with a seed template, like Angular Seed.
Just remember that you want to keep your module('app').controller('whatever') inside whatever.js, and any other .factory('forWhatever') (like in your example) should be contained with that parent .controller('whatever') inside the whatever.js file.
I would like to have few global variables that are UI related (i.e. open menu state). I decided to put these in $rootScope so they're always accessible.
This is the code I've written:
(function (angular) {
angular
.module("App", [])
.run(["$rootScope", function ($rootScope) {
angular.extend($rootScope, {
ui: {
menu: false,
...
}
});
}]);
})(angular);
I've deliberately used angular.extend, to make sure that consecutive manipulations to the same object are retained. And I think it's also more clean and safe than adding several properties to any object one by one.
Problem
Upper code doesn't do anything though. When I run my application and check root scope by calling:
$("body").scope().$root.ui
I get undefined until some property within ui gets manipulated by ng-click directives on my application. Only then my ui gets a reference... But it's still not the one I've defined in the run() function but rather angular generated object property that ng-click directive generated as per expression.
What am I doing wrong?
Resolved - module got overwritten
Ia managed to resolve it myself. Code contained in the upper question isn't sufficient to show the actual problem in my application. The problem was the way I was loading module requirements and file ordering.
I'm loading files in this order:
app.js
routing.js
service.something.js
...
filter.something.js
...
So I thought to add module requirements to my app module in subsequent files (make ti actually modularized). This would make it simple to either include or exclude particular files without any runtime errors. It would also allow loading additional files dynamically as application runs.
The problem with my code was that I've overridden my original module in subsequent files. When I added all module requirements into app.js everything everything started working.
Possible workaround
I can see that I'm not the only person that would like this kind of functionality. Lasy module requirements loading is possible as per this Google groups' post.
What it does is it creates a new injector function
instanceInjector.loadNewModules = function (mods) {
forEach(loadModules(mods), function(fn) { instanceInjector.invoke(fn || noop); });
};
that can later be used by individual modules to add themselves as requirement to the main application module by doing this:
$injector.loadNewModules(["Module1", "Module2", ...]);
Although it would be much better (my opinion) if there was an additional function on Module type called requires() so one could do this instead:
angular.module("MainModule").requires(["AdditionalModule", "OtherModule", ...]);
I think that would make it more concise and easy to use and understand.
I have a question related to modules and routing in angularjs. The requirements are to define all routing configs in one module - lets call this ModuleRtr.
Once the route is triggered, it should call a controller (called TestCtr for example). This controller is defined in another module - let's call it ModuleCtrl.
If I try to do that, I got an exception like:
"Argument TestCtr is not a function, got undefined"
. The reason is that when angular broadcast $routeChangeSuccess event, the listener tries to access the controller (TestCtr) as part of the current module - ModuleRtr. Because it's not there, it throws an error.
If I simply create TestCtr controller in ModuleRtr (the same that has the route in it), then everything works. But I don't want that, I want to have my TestCtr in different module. I also don't want to have route define in ModuleCtrl module.
So, in more straightforward way, my question is: Is it possible a route defined in one module (ModuleRtr) to call a controller defined in another module (ModuleCtrl)?
Something that I forgot to mention...I don't want to bind these 2 modules by any means. That of course includes listing a dependency during module's creation. I have already tried dynamic loading of TestCtr - it didn't solve the problem.
The scenario is: You have 2 angularjs applications (modules). They don't know anything about each other...except one thing - somewhere in a shared/common location, there is an object which follows a particular structure (like a contract). The first module writes data there. Then it runs a common function from the second module (this is actually the question I am asking - how?). Then the second module knows already where to go (it's a contract) what to read and what to do. One way I can do this is to try dynamically generates the string that represents a module dependency when the other module is created. I am not sure if that is a good solution...
Many thanks!
You can use a single module with submodules for each functionality, such as:
angular.module('myApp.home',[]);
angular.module('myApp.routing',[]);
...modules here...
angular.module('myApp', [
'myApp.home',
'myApp.routing'
]);
So you can send a method from myApp.home calling a intermediate method from myApp and this one calling the myApp.routing method.
At least, this is how I see it.