Can AngularJS inject named instances of factories or services? - angularjs

I am just starting with Angular with a project that seems really suited to it. In this project i must make several instances of a form builder so i have decided to make a service out of the form builder code. All is fine and good up until i take in account the other requirement: Form previews.
I was thinking of something along the lines of what this guy does but then i realised using his approach implies i cannot store/share more than one form (At least with the default injection approach used by Angular) so i gave it some thought and decided that having one instance of the FormBuilder service for each form would cut it. How can i control which instance of my service is injected into my controllers?

Propably you would not inject a specifc FormBuilder instance rather than a InstanceRegistry?

Create a service which returns a function taking the name to resolve and returns the resolved instance. This will be called from your controller.
Optionally, you could create resolves for the route if you are using either ngRoute or ui.router and do the resolving in the resolve block.
.when("...",{
controller:"...",
templateUrl:"...",
resolve:{
form1:["$formFactory", function($formFactory){
return $formFactory("form1")
})
}
})
HTH

Related

How to override or add some functionality to the existing AngularJS services?

I want to override or add some more functionality to existing services like $http, $log and so on
how to do that?
You would need to use the $provide.decorator method for extending any angular services, the definition of a decorator as per the angular docs:
A service decorator intercepts the creation of a service, allowing it to override or modify the behavior of the service. The object returned by the decorator may be the original service, or a new service object which replaces or wraps and delegates to the original service.
Came across this link by Freek Wielstra which might help you in taking this further.
Edit:
Please check this SO answer by #tomakisquare, he has provided a brilliant plunkr example to extend third party services (or any service for that matter) without meddling with the original code.

How do you inject dependencies into services in angular.js?

I'm using AngularFire to create a web app. Several of my controllers use a lot of the same functions to access the data in Firebase, so I am trying to write a service so that I don't have to rewrite the same functions for every controller. The problem is that I can't seem to get the Firebase dependency into the service. I'm using the following code:
angular.module("myApp", ["firebase","ngDraggable"])
.factory("GetData",['$firebase','FirebaseConn',function($firebase,FirebaseConn){
$firebase(new Firebase("https://XXXX.firebaseio.com/")).$asObject().$bindTo(scope, "firebaseData");
return {
};
}]);
But when I try to run this, I get the following error:
Unknown provider: FirebaseConnProvider <- FirebaseConn
I am able to access Firebase through my controllers, so it's not a problem connecting to firebase.js or angularfire.js.
How should I inject Firebase into my service so I can access the data in all of my controllers? Or, is there a better way to go about this? I'm rather new to Angular so if there's a better way to share functions between my controllers I'm all ears.
You inject them precisely the same way that you do in Controllers and Directives.
This is a common error in AngularJS, and it means you're injecting something that isn't injectable. It almost always means either you missed a dependency (probably not in this case) or that you're asking for something that doesn't exist in the first place.
This is almost certainly your problem. You're asking for firebase and getting it, but it can't find FirebaseConn. What is that, some variable of yours that you're using to track your connection? Because you aren't using it, and the AngularFire docs I just looked at don't, either.
Consider something more like the following:
angular
.module("myApp", ["firebase", "ngDraggable"])
.service("firebaseManager",['$firebase', function($firebase) {
var ref = new Firebase("https://XXXX.firebaseio.com/"),
sync = $firebase(ref);
this.getData = function() {
return sync.$asObject();
};
});
Obviously, customize this to suit. Two comments:
You probably do want a service instead of a factory. This is a common point of confusion when you first start using AngularJS. You only need a factory if you plan to get involved in the instantiation of the service in some way. A service is just a shortcut form of a factory with the most common usage - the one you probably want.
You will now inject this service firebaseManager into your controllers. When you do, they will be able to call firebaseManager.getData() and any other methods you define. firebaseManager will be a singleton, so all of this will go through one common Firebase connection.

AngularJS Provider dependency injection - using $http in provider?

tl;dr
I'm really struggling to find the appropriate pattern here. How should I best configure a generalized provider to a specific use-case? I can't use $http as a dependency in .configure(); can I?
longer, boring explanation:
I am trying to create a generalized provider which I may reuse in Angular. I have it working, however it requires configuration.
The intention is to provide a fallback REST service to use in saving data to the server, but with provision to save offline in local-storage. Therefore, I need to provide appropriate $http calls for each instance of this provider.
Is it possible to provide appropriate $http calls with .configure() or else should I try and figure out how to inject $http into the provider from the start and then configure it afterward??
It's frustrating... and may change in AngularJS 2.0... But for now, yes, it is not possible to do this. There is a very high wall between the .configure() and .run() states, so you can't access $http from a .configure() function. The reason is that it hasn't actually been created. At this stage, all that exists is the provider. Once all of the dependencies are configured, then the http provider will be used to make the real $http service.
I'm not sure exactly what you're trying to do, but there are two excellent AngularJS developers that are good to follow who have some advanced patterns in projects they've shared: Pascal Precht and Brian Ford. Here are two projects that make heavy use of provider/service concepts as well as $http-driven services:
https://github.com/angular-translate/angular-translate
https://github.com/btford/angular-modal
Angular Modal, especially, does $http work to load its templates. There might be use cases in there that are similar to what you're trying to do.

Dynamically add service to $injector

I'm trying to dynamically create a service in another service and add it to the inejctor, so that other controllers and services throughout the app can inject it later. I'm not sure if what I'm even trying to do is possible but I've boiled down what I'm trying to do into an example on Plunkr
I'm basically having two modules use each other. One defines how a service should be configured on the fly, and the other module configures the services on the fly. I'm not sure what to do while configuring the new dynamic service though so that it can be found by the injector later and used in other controllers,services etc. Any thoughts?
Ok, so basically I needed to make a provider instead of a service. The provider can create factories, values, constants, etc. See a revised plunker here

Is it possible to create an AngularJS service without a module?

In AngularJS there is a short form to create controllers, so you do not have to use a module for this. This short form is to simply define a function
function FooController ($scope) {
// ...
}
and reference it from the HTML markup using ng-controller:
<div ng-controller="FooController">
...
</div>
Now, my question is, whether there is a similar "short form" to define services? In other words: Can you define (and use) a service without using a module?
Please note that I know that it perfectly makes sense to structure your applications using modules, and not doing so could / should be regarded as bad practice. It's just that I am explaining AngularJS to someone who's completely new to it, and the question arose today. So it's just for curiosity and completeness.
Quoted from the doc of Creating Services
To register a service, you must have a module that this service will
be part of.
So I guess the answer is no.
Since the ng module is always loaded, you could define your service on the ng module:
angular.module('ng')
.service('aService', function () {
// you really shouldn't do this
});
It works, but you shouldn't be messing with a module that you don't own.
If you're trying to explain to someone why using your own modules with .controller is good:
Talk to them about testing. It's a lot easier to mock things if you're using modules
If you need to have other modules as dependencies (like angular-ui)
If you want to decorate another service (e.g. $http)
If you need to register directives, filters, animations, etc.
It's a lot nicer to have modular code :)
It's an angular concept I don't understand at all, I always believed "separation" is good, so I dont get why we need to associate a service to a specified application.
Here what I am doing: you can declare your angularjs application as a global object:
window.markrApplication = angular.module('markrOptionsApp', ....)
And declare all your services like this:
markrApplication.service('data', ....
Of course you need to have all the dependencies set on all your angularjs application.

Resources