angular - circular dependency - angularjs

For the first time ever I am facing this issue and I am struggling a lot in trying to figure out why and how to fix it.
I have two services, service1 and service 2, but apparently, there's a circular dependency like this:
serv1 <- serv2 <- serv1
The services code is the following:
angular.module('service1', [])
.service 'serv1', ['$rootScope','$http','$location','serv2',
function ($rootScope, $http, $location, serv2){
serv2.doMyOtherThing(...)
}
]
and service2 is the following:
angular.module('service2', [])
.service 'serv2', ['$rootScope','$http','$location','serv1',
function ($rootScope, $http, $location, serv1){
serv1.doMyThing(...)
}
]
why is there a circular dependency? how do I solve this?
Each service is specific for something (serv1 variou utilities and serv2 array utilities) and I need to use the two together sometimes but it's currently not possible.
Thanks for any help

If you see this Miško Hevery's blog you will understand that :
...
.service 'serv1', ['$rootScope','$http','$location','serv2'
.service 'serv2', ['$rootScope','$http','$location','serv1',
The serv1 needs serv2 and serv2 needs serv1. And this is going to train a circular dependency.
So you could use a third service
Or you can resolve this like this :
angular.module('service1', [])
.service 'serv1', ['$rootScope','$http','$location','serv2',
function ($rootScope, $http, $location, serv2){
serv2.doMyOtherThing(...)
}
]
angular.module('service2', [])
.service 'serv2', ['$rootScope','$http','$location','$injector',
function ($rootScope, $http, $location, $injector){
var serv1 = $injector.get('serv1');
serv1.doMyThing(...)
}
]

Use a third service, use that third service in the other ones.
example:
angular.module('service1',[])
.service 'serv1' [..,'servCommon', function(..,servCommon){}]
angular.module('service2',[])
.service 'serv2' [..,'servCommon', function(..,servCommon){}]
angular.module('serviceCommon',[])
.service 'servCommon' [.., function(..){}]
Add some common function in that servCommon and use them from other two.
Hope this helps.

Related

AngularJS: Error: $q is not defined

I want to make a promise in my angularjs controller. I took the example from the Angularjs Doc and pasted it in my controller. When I try to run the code, the console prints:
Error: $q is not defined
Why is this error happening and how do I solve it?
I tried to google this problem, but most questions revolve about more specific problems than mine.
A (german) guide tells me that promises are already in angular js implemented and there is no need to add anything to it.
EDIT:
this is my controller:
app.controller("ArgumentationController", [
'$scope', '$resource',
function($scope, $resource) {
EDIT2:
A commentor suggested to inject $q. I did this:
app.controller("ArgumentationController", [
'$scope', '$resource', '$q',
function($scope, $resource, $q) {
Now, the error does not occur.
From your past code, no need of $resource in your code. Instead inject $q in it.
As you are creating a dummy promise using $q, make following changes.
app.controller("ArgumentationController", [
'$scope', '$q',
function($scope, $q) {

how to limit dependency injections in angularjs

I used dependency injections in my controllers as follows.
.controller('deals_list', function ($scope, global, config, services, dealService, pagination) {
Now the app was growed. Dependencies are growing too. I want limit these injections. So is there a way to limit those with global injections or something?
What kind of procedure actually should I follow?
var myApp= angular.module('myApp', []);
myApp.run(function ($rootScope, $location, $http, $timeout, YourService) {
$rootScope.MyService = YourService;
}
Used it into controller :
myApp.controller('YouCtrl', ['$scope', function ($scope) {
// scope inherits from root scope
$scope.MyService.doSomething();
}]);
What i believe you can do is to create a service that contains all the services that you want to use. The global service is like a facade into your real service.
The option then are to create on global service with all dependencies included. Or multiple facade service which group these services
app.service("Configurations",function(global,config) {
this.global=global;
this.standard=config;
});
app.service("AppServices",function(services, dealService, pagination) {
this.services=services;
// other assigments
});
Now you can inject Configurations and AppServices
This at least gives some visibility into what your controllers are dependent upon.

Conditionally inject angular module dependency

I'm new to angular and have the following code.
angular.module('MyApp')
.controller('loginController', ['$scope', '$http', 'conditionalDependency',
function ($scope, $http, conditionalDependency{
}
I would like to have conditionalDependency loaded conditionally. Something like this
if(true)
{
//add conditionalDependency
}
How can this be done. I've seen this post . However, my requirement is that I have the dependency specified in function
Thanks in advance.
Not quite clear as to why you would have to have it in a named function like in your example but...
If you need conditional dependencies, I would suggest taking a look at the following:
Conditional injection of a service in AngularJS
I've used this method in a couple niche scenarios and it works quite well.
EXAMPLE:
angular.module('myApp').controller('loginController',
['$injector', '$scope', '$http',
function($injector, $scope, $http) {
var service;
if (something) {
service = $injector.get('myService');
}
});
You can use it even without injecting injector in your controller
if(something){
var injector = angular.element(document).injector();
var myService = injector.get('myService')
}
Use:
angular.injector().get('conditionalDep');
You can inject $injector once to your file and call $injector.get('dep');

accessing $window and $logProvider in angular

When I am trying this (CoffeeScript)
.config ['$logProvider', '$window', ($logProvider, $window) ->
//...do something with parameters...
]
I get "$window not defined", and whe I try run block
.run ['$logProvider', '$window', ($logProvider, $window) ->
//...do something with parameters...
]
I get "Unknown provider: $logProviderProvider <- $logProvider"
I there any way I can use both?
Providers are only scoped at config time, then their provided service is available:
.config ['$logProvider', ($logProvider) ->
$logProvider.debugEnabled(true);
]
.run ['$log', '$window', ($log, $window) ->
$log.debug('hello logger!');
]
Note that $window is not a provider thus can't be configured.
Your answer is: .config handles pure module configuration. Once done, factories are ready so you can use everything you need. In your case, you actually need $log and $window.

Injecting a service into another service in angularJS

Is it possible to inject one service into another service in angularJS?
Yes. follow the regular injection rule in angularjs.
app.service('service1', function(){});
//Inject service1 into service2
app.service('service2',function(service1){});
Thanks to #simon. It is better to use Array injection to avoid minifying problem.
app.service('service2',['service1', function(service1) {}]);
Yes. Like this (this is a provider, but same thing applies)
module.provider('SomeService', function () {
this.$get = ['$q','$db','$rootScope', '$timeout',
function($q,$db,$rootScope, $timeout) {
return reval;
}
});
In this example, $db is a service declared elsewhere in the app and
injected into the provider's $get function.
In order to avoid any confusion, I think it is also worth mentioning that if you are using any other services (e.g. $http, $cookies, $state) in your childService, then you also need to explicitly declare them.
e.g.
function() {
var childService = function($http, $cookies, parentService) {
// Methods inherited
this.method1Inherited = parentService.method1();
this.method2Inherited = parentService.method2();
// You can always add more functionality to your child service
angular.module("app").service("childService", ["$http", "$cookies", "parentService", childService]);
}());
You can either declare the services you are using inside your child in an array and then they get injected automatically, or inject them separately with the $inject annotation:
childService.$inject = ["$http", "$cookies", "parentService"];
angular.module("app").service("childService ", childService );

Resources