Angularjs simple meaning of module and Dependency - javascript

Hello I am New to angularjs
var app = angular.module('app', [])
app.controller('ProductController', ['$scope,$htttp', productController]);
Please correct me if i am wrong
This above two line is saying we have created the module name app
and we have controller called productController and have $scope, $http as a dependency.
App is starting point of our angularjs application.
Controller is basically for business logic.
what is the servieces ,Factory ?
what is Dependency Injection in simple words ?
I want to understand it more clearly as i study on angualar.js also. but unable to understand it clearly.
Please help to provide me some simple understanding on this

angular.module create module for application, and an application can one or more than one module. It's for modularity. so if you want to initialize core module. then you have to
var app=angular.module("core.module", [
/* Shared Modules */
"services",
"widgets",
"layout"])
So what it does it will initialize every module for application.so by using app object you can directly create common directive for all the modules and much more.
core.module is behaves like constructor and what you want to initialize will pass in "[]" during the call of constructor. it's up-to you.
You can call it as dependency.
In every module you can have different controllers but one thing always keep in mind whenever you add script file reference in html then do add child modules first then core otherwise it will give error. Module not defined.
Service and Factory pretty much they both are equivalent. Most important is to realize that both are singletons.
Factories are functions that return the object, while services are constructor functions of the object which are instantiated with the new keyword.
Services:
angular.module('app').service('abcservice', function() {
this.getdata= function() {};
});
Factory:
angular.module('app').factory('TestFactory', function() {
return {
someFunction: function() {}
};
});
when you want to use services and factory in our application then you have to pass it as argument/dependency in controller declaration.
app.controller(controllerId, ['$scope','abcservice','TestFactory']);
For much please refer Angular Tutorial

Related

Prevent Third Party Factory Interfering with My App's Factory with the Same Name

I am using angular-bootstrap-colorpicker in my app and am having a weird issue. The colorpicker module has a factory named Slider. That's causing the colorpicker not to work because my app also has a factory called Slider. Refactoring every occurrence of this in the app isn't possible, and it seems like a sloppy workaround anyway. The error being thrown is
Uncaught TypeError: Slider.setSaturation is not a function
which I've concluded is because my app's factory has no method setSaturation and Angular is "confused". I don't really know enough about factories and how Angular organizes them, but it seems very odd that they would be available across modules like that. eg
angular.module('thomasApp', [])
...
.factory('Slider', ...
is affected by
angular.module('colorpicker.module', [])
...
.factory('Slider', ...
or vice versa.
Is there someway I can compartmentalize this colorpicker so that it does not interfere with my Slider factory?
Edit:
I agree with the linked answer that using a prefix as a namespace is a smart idea. However that would require an unrealistic amount of refactoring. I appreciate the answer below but it isn't fleshed out enough for me to be able to put into action.
1) Is this really the best possible solution (apart from prefixing from the project's beginning)? - If I make a change like this, will it be erased the next time I do a bower update, or someone pulls down my project and does a bower install?
2) Is there a better way? - If not, can the current answer be expanded and have explanations of what's happening added?
The problem that you have is general already known issue in Angular. #fracz was right, it's connected with Modules and namespace / name collision in AngularJS. The issue is that Angular has only one $injector instance per module instantiatation and all defined injectable objects go into it. By injectable objects I mean constants, values, services, controllers, directives.. This is bad in cases as this one because even if we modularize our application by defining multiple modules and dependencies between them at the end all the defined injectable objects end up in a same context/namespace/injector.
Angular makes this even worse by not using fail-fast technique in such cases and because the application continues working you may end up noticing the issue late which often can lead to expensive refactorings. And there is still a question how we can improve this, IMO failing-fast at least will help in avoiding this issue at it's beginning.
However in your case you are lucky that the library is really small and what you need is only the color picker directive. I have made a workaround example here by defining the color picker directive in your module while taking it's definition from the instantiated library module $injector. Like this you are free to change even it's name :).
Code example:
// NOTE: redefine the directive
app.directive('colorpicker', function () {
var injector = angular.injector(['ng', 'colorpicker.module']);
return injector.get('colorpickerDirective')[0];
});
For clarification purposes there is also an example that shows how Angular behaves when you define two service with the same name. The application successfully continues working with the last service definition.
I hope that this answer makes the things clear and successfully solves your problem. If you have more questions feel free to ask. Cheers!
Maybe something like this - create a fake module and wrap the existing provider under a new name. This will isolate the dependency.
var colorpicker = angular.module('my-colorpicker', ['colorpicker.module']);
colorpicker.factory('ColorPickerSlider', function() {
var injector = angular.injector(['colorpicker.module']);
var Slider = injector.get('Slider');
return Slider;
});
I know that this doesn't solve the fundamental problem of namespaces but it gives a way of hiding existing dependencies in a sandbox.
Yes, you can handle multiple factories with same name.
Here is the example,
var app = angular.module('firstApp', []);
app.factory('SameFact', [function () {
return { Name: "First" };
}]);
var app2 = angular.module('secondApp', ['firstApp']);
app2.factory('SameFact', [function () {
return { Name: "Second" };
}]);
app2.controller("testController", ["SameFact", "$scope", "$injector", function (SameFact, $scope, $injector) {
$scope.myName = {};
$scope.myName.Name1 = SameFact.Name; // This will be "Second", Last factory
var inj = angular.injector(['firstApp']);
$scope.my_inject = inj.get('SameFact').Name; // This will be "First", the first factory
}]);
Note
When you pass a factory as a dependency to a controller, it will register the last registered factory.
That is, in this example, I have registered two factory with same name SameFact but in different module.
When I refer the factory SameFact from my controller it will always point to the factory which is registered last, ie, factory in secondApp.
But, you can manually refer the factory which is in the module firstApp.
You can use angular.injector(['module_name']) to select injector of your required module and then use get() function inside it to get your factory or service.
Conclusion
So, you need declare a scope variable which point to your Slide factory of colorpicker module. And use this scope variable to get all required operations within colorpicker module. Find where the place where you are calling functions of colorpicker and replace it with this new variable.
Hope this will help you to survive your current situation.
Feel free to ask any doubts regarding this !!!
Place colorpicker.module preceeding your module that's containing Slider factory, at your module initialization :
angular.module('thomasApp', ['colorpicker.module','anotherModule'])
Here is an example on js fiddle

How does implicit/inline/$inject dependency injection work in AngularJS?

I'm new to AngularJS and I would like to understand more about the dependencies that are being injected by default. While reading through code I've noticed that sometimes dependencies are explicitly declared beforehand, and sometimes they aren't. For example:
someModule.controller('MyController', ['$scope', 'someService', function($scope, someService) {
// ...
}]);
Gives the same results as:
someModule.controller('MyController', function($scope, someService) {
// ...
});
How does this work? Is Angular assuming that the modules being injected are named the same as the variables in the parameters?
Also, strangely enough, if you do specify the dependencies that are going to be injected, you must specify all of them and in the right order, otherwise nothing will work. For example, this is broken code:
someModule.controller('MyController', ['someService', '$scope', function($scope, someService) {
// Won't give us any errors, but also won't load the dependencies properly
}]);
Can someone clarify to me how is this whole process working? Thank you very much!!
Yes, dependency injection in Angular works via the names of the components you (and Angular - for the internal ones) registered.
Below is an example showing how a service is registered and injected into a controller using several different annotations. Please note that dependency injection always works the same in Angular, i.e. it doesn't matter if you are injecting something into a controller, a directive or a service.
app.service('myService', function () {
// registering a component - in this case a service
// the name is 'myService' and is used to inject this
// service into other components
});
Two use (inject) this component in other components, there are three different annotations I am aware of:
1. Implicit Annotation
You can either specify a constructor function which takes as parameters all the dependencies. And yes, the names need to be the same as when these components were registered:
app.controller('MyController', function ($http, myService) {
// ..
});
2. Inline Array Annotation
Or you can use a notation using an array, where the last parameter is the constructor function with all the injectables (variable names do not matter in this case). The other values in the array need to be strings that match the names of the injectables. Angular can this way detect the order of the injectables and do so appropriately.
app.controller('MyController', ['$http', 'myService', function ($h, m) {
/* Now here you can use all properties of $http by name of $h & myService by m */
// Example
$h.x="Putting some value"; // $h will be $http for angular app
}]);
3. $inject Property Annotation
A third option is to specify the $inject-property on the constructor function:
function MyController($http, myService) {
// ..
}
MyController.$inject = ['$http', 'myService'];
app.controller('MyController', MyController);
The reason why the last two options are available, at least as far as I know, is due to issues which occured when minifying the JavaScript files which led to the names of the parameters being renamed. Angular then wasn't able to detect what to inject anymore. In the second two cases the injectables are defined as strings, which are not touched during minification.
I would recommend to use version 2 or 3, as version 1 won't work with minification/obfuscation. I prefer version 3 as from my point of view it is the most explicit.
You can find some more detailed information in the internet, e.g. on the Angular Developer Guide.
Just to provide a different sort of answer, as to the how inline/implicit dependencies work in AngularJS. Angular does a toString on the provided function and parses the parameter names from the string which is produced. Example:
function foo(bar) {}
foo.toString() === "function foo(bar) {}"
References:
source code
AngularJS Dependency Injection - Demystified

Why are Factories more flexible than Services in AngularJS?

According to this source,
Why do the two styles exist if they can accomplish the same thing?
Factories offer slightly more flexibility than services because they
can return functions which can then be new'd. This follows the factory
pattern from object oriented programming. A factory can be an object
for creating other objects.
I'm having trouble connecting this piece of information to the concept of constructors in Javascript and object / prototype. Can someone help me connect the dot? Thanks.
Service VS Factory
A service is a constructor function that can be called with 'new' where as a factory returns an object that you may run some code before that is why it is more flexible.
To see a detailed example please check out this question. matys84pl talks about it in detail.
Factory
These are practically singletons. So for instance you can hold data across calls to it.
factory('myFactory', function () {
var internalList = [];
return {
add: function (value) { internalList.push(value); },
get: function () { return internalList; }
}
});
As you could imagine, if controller1 pushed Hi into the list and controller2 called get() immediately after, it would recieve [ 'Hi' ].
Service
From the angular docs
JavaScript developers often use custom types to write object-oriented code.
service('UnicornLauncher', function (apiToken) {
this.launchedCount = 0;
this.launch = function() {
// Make a request to the remote API and include the apiToken
...
this.launchedCount++;
}
});
Provider
For some bonus reading, I'll tell you about a provider. A provider wraps a factory. Why? Because there are two phases in an angular application, the configure phase and the run phase. Services, factories and values AREN'T available during the run phase.
So, say we need to configure a service before it is injected into the controllers. We need to use a provider.
The angular docs have a nice example:
provider('unicornLauncher', function UnicornLauncherProvider() {
var useTinfoilShielding = false;
this.useTinfoilShielding = function(value) {
useTinfoilShielding = !!value;
};
this.$get = ["apiToken", function unicornLauncherFactory(apiToken) {
// let's assume that the UnicornLauncher constructor was also changed to
// accept and use the useTinfoilShielding argument
return new UnicornLauncher(apiToken, useTinfoilShielding);
}];
});
so this.$get is basically the second argument of the factory('...', ....
So if we use this in the configure phase we do this:
config(["unicornLauncherProvider", function(unicornLauncherProvider) {
unicornLauncherProvider.useTinfoilShielding(true);
}]);
Notice how we ask for unicornLauncherProvider, we add that Provider suffix. Yet when we named our provider we didn't supply it. That is because angular automatically adds the suffix for you. If you want to access the service this provider creates, ask for the unicornLauncher.
I had an 'Eureka effect' when i realized that service & factory are only syntactic sugar for provider (https://docs.angularjs.org/api/auto/service/$provide#provider)
The only difference between these two is the way Angular processes the passed value before providing it with the injector.
When I get the object from the injector, I usually can't tell if it has been created using a service or a factory (or any of the other $provide methods)
So the Question is "How do I want to implement this?" and not "How do I want to use this?".

AngularJS UI Router using resolved dependency in factory / service

I have a UI Router defined something like this (trimmed for simplicity):
$stateProvider
.state('someState', {
resolve: {
model: ['modelService', 'info', function (modelService, info) {
return modelService.get(info.id).$promise;
}]
},
controller: 'SomeController'
});
This someState state is using a factory / service that is dependent on that model resolve. It's defined something like this, and AngularJS throws an Unknown provider: modelProvider <- model <- someService error here:
angular
.module('someModule')
.factory('someService', someService);
someService.$inject = ['model'];
function someService(model) { ... }
However, using the same model resolve inside of this state's controller works fine:
SomeController.$inject = ['model'];
function SomeController(model) { ... }
So I'm understanding that UI Router is delaying the DI of the SomeController until the resolve is happening, which allows AngularJS to not throw an error. However, how come the same delay is not happening when putting that resolve as a dependency on someService? Do resolves only work on controllers? And if that is the case, how can I use a resolve inside a factory / service?
Do resolves only work on controllers?
Yes, resolves only work on controllers.
And if that is the case, how can I use a resolve inside a factory / service?
Remember that factories and services return singleton objects, i.e. the first time a factory is injected into a controller, it runs any instantiation code you provide and creates an object, and then any subsequent times that factory is instantiated, that same object is returned.
In other words:
angular.module('someModule')
.factory( 'SomeFactory' , function () {
// this code only runs once
object = {}
object.now = Date.now();
return object
);
SomeFactory.now will be the current time the first time the factory is injected into a controller, but it not update on subsequent usage.
As such, the concept of resolve for a factory doesn't really make sense. If you want to have a service that does something dynamically (which is obviously very common), you need to put the logic inside functions on the singleton.
For example, in the code sample you gave, your factory depended on a model. One approach would be to inject the model into the controller using the resolve method you've already got set up, then expose a method on the singleton that accepts a model and does what you need to do, like so:
angular.module('someModule')
.factory( 'SomeFactory', function () {
return {
doSomethingWithModel: function (model) {
$http.post('wherever', model);
}
});
.controller('SomeController', function (SomeFactory, model) {
SomeFactory.doSomethingWithModel(model);
});
Alternatively, if you don't need the resolved value in the controller at all, don't put it directly in a resolve, instead put the resolve logic into a method on the service's singleton and call that method inside the resolve, passing the result to the controller.
It's hard to be more detailed with abstract conversation, so if you need further pointers then provide a specific use-case.
You cannot use the resolved values in services or factories, only in the controller that belongs to the same state as the resolved values. Services and factories are singletons and controllers are newly instantiated for (in this case) a state or anywhere else where ng-controller is used.
The instantiation happens with the $controller service that is capable of injecting objects that belong only to that controller. Services and factories do not have this capability.
You should review the angular docs on dependency injection:
Components such as services, directives, filters, and animations are defined by an injectable factory method or constructor function. These components can be injected with "service" and "value" components as dependencies.
Controllers are defined by a constructor function, which can be injected with any of the "service" and "value" components as dependencies, but they can also be provided with special dependencies. See Controllers below for a list of these special dependencies.
The run method accepts a function, which can be injected with "service", "value" and "constant" components as dependencies. Note that you cannot inject "providers" into run blocks.
The config method accepts a function, which can be injected with "provider" and "constant" components as dependencies. Note that you cannot inject "service" or "value" components into configuration.
So each type of angular component has its own list of acceptable components to inject. Since services are singletons, it really wouldn't make any sense to inject a value as part of a resolve. If you had two separate places on your page that used a service with different resolves, the outcome would be indeterminate. It would make no more sense than injecting $scope into your service. It makes sense for controllers because the controller is responsible for the same area of the page that is being resolved.
If your someService needs to use the data in model, it should have a function that takes the data as a parameter and your controller should pass it.

AngularJS DI for custom functions

I've been working a lot lately with AngularJS and I really like the dependency injection stuff. I'm using it all over the place, but just in Angular components, like controllers and the like.
This always calls on the angular object:
angular.module('app').controller(/**/);
Now I have this function:
var custom = function(MyService) {
// do stuff
};
I've declared the Service this way:
angular.module('app').factory('MyService', function($rootScope) {
return {
show: function() {
// do stuff
};
},
hide: function() {
// do stuff
}
};
});
I now want to use this service in my custom function. Is there a way of manually calling the angular DI container? (I couldn't find anything in the docs...)
I know that this works for controllers not defined with the angular.module()... thing:
function Controller(MyService) {
MyService.hide(); // works
}
But how to use it outside of AngularJS components, in completely independent functions?
Or do I have to take a completely different path to achieve my goal?
Cheers and thanks in advanced,
Christian
angularjs is pretty neat in the fact that it exposes its own internal services to the user. The service you're looking for is $injector
What you want to use to call your custom function is $injector.invoke(myCustomFunction,thisForCustomFunction,{named:locals});
If you are by chance wanting to invoke this function outside of angular you'll have to get the applications injector.
var injector = angular.element(elementWithNgApp).injector();
Note:
The invocation time may be reduced though. As the injector must annotate (find what services you need) using several regular expressions. The reason this is not an issue throughout angular is because it is done once. Because services,factories,providers, are all instantiated (newed) singletons that provide closure with the services and whatever uses the services inside your providers
To prevent this extra step you can provide a $inject property on your function.. Something like this:
myfunction.$inject = ['ServiceA','ServiceB'];
function myfunction(a,b){
//a is ServiceA
//b is ServiceB
};

Categories

Resources