Angular - Issue in moving service into separate file - angularjs

I have a service with a few methods:
function userService($http, API, auth) {
....
}
and then used in my module like:
var app = angular.module('app', ['ngRoute'])
.service('user', userService)
...
All of this is in my app.js file, I want to separate things so its easier to maintain. I'm trying to use the line .service('user', '/services/userService') but its not working any ideas how to i need to reference this?
Thanks.

I think you are creating a new module instead of use yours.
To retrieve an existing module and use it in a separated file, you have to do :
var app = angular.module('app')
.service('user', userService')
// ...
Instead of
var app = angular.module('app', ['ngRoute'])
.service('user', userService')
// ...
Documentation available at https://docs.angularjs.org/guide/module#creation-versus-retrieval
EDIT from #koox00 answer
Don't forgot to load all files related to your module in your markup, in the good order (before load the file containing your module declaration).

Related

Angular 1: $injector can't find a provider dependency when injecting provider inside a provider

My use case is: we have several helper classes, A and B, that are services, A depends on B, and I wanted to make them providers so that they can be used in .config phase.
I followed this SO answer to load a provider inside a provider.
As you can see here, it works:
http://plnkr.co/edit/SIvujHt7bprFumhxwJqD?p=preview
var coreModule = angular.module('CoreModule', []);
coreModule.provider('Car', function() {
//CarProvider.engine
this.engine = 'big engine';
//Car
this.$get = function() {
return {
color: 'red'
};
};
});
coreModule.provider('ParameterService', ['$injector', function($injector) {
try {
var CarProvider = $injector.get('CarProvider');
this.deepEngine = CarProvider.engine;
console.log('deepEngine = ' + this.deepEngine);
} catch (e) {
console.log("nope!")
}
// ParameterService
this.$get = function() {
return {};
};
}]);
coreModule.config(function(CarProvider) {
console.log('configEngine = ' + CarProvider.engine); // big engine
});
This works if I have Car and ParameterService in one file in this order.
However when I split Car and ParameterService into multiple files on disk, or I define ParameterService before Car in the same file, $injector.get('CarProvider') inside ParameterService fails.
How do I fix the issue?
I want to have one provider/service per file and I don't understand what is missing.
The order in which the services are defined doesn't matter during run phase, where service instances are injected. But it does matter during configuration phase, where service providers are injected, i.e. in provider constructors and config blocks.
Providers and config blocks are executed in the order in which they are defined. If Car provider is defined after ParameterService provider or config block, CarProvider doesn't exist at the moment when those two are executed.
To avoid potential race conditions, one module per file pattern should be followed. This allows to keep the app highly modular (also beneficial for testing) and never care about the order in which the files are loaded. E.g.:
angular.module('app', ['app.carService', 'app.parameterService']).config(...);
angular.module('app.carService', []).provider('Car', ...);
angular.module('app.parameterService', []).provider('ParameterService', ...);
Module parts are executed in the order in which the modules are defined in angular.module array hierarchy, from children to parents.
The decision if config block needs its own module depends on what it does (mostly for testing reasons).
It is possible to have providers in different files. You just need to attach them to the first module that you created.
If your markup looks like this:
<script src="coreModule.js"></script>
<script src="parameterService.js"></script>
Then, in coreModule.js, define your module:
angular.module('CoreModule', [])
.provider('Car', function() {
...
}
Remember, the second parameter ([]) tells angular to create a new module.
Then, declare your other provider in a different file, and attach it to your existing 'CoreModule' module:
angular.module('CoreModule')
.provider('ParameterService', ['$injector', function($injector) {
...
}
Notice that we are only passing one parameter to .module(). This tells angular to add your provider to an existing module.
Plunkr Demo

Dependencies Between Modules - Controllers?

This tells AngularJS that all values, factories and services defined inside the myUtilModule should be available inside the myOtherModule module too. In other words, myOtherModule depends on myUtilModule.
var myUtilModule = angular.module("myUtilModule", []);
myUtilModule.value ("myValue" , "12345");
var myOtherModule = angular.module("myOtherModule", ['myUtilModule']);
myOtherModule.controller("MyController", function($scope, myValue) {
});
My question is: What if you define controllers inside myUtilModule and try to use them on myOtherModule. Is this possible?
Yes, controllers will also be available between modules, a pratical example could be as follows:
angular.module('test.controllers').controller('HomeCtrl');
and then on your main module:
angular.module('test', [
'test.controllers',
'test.services',
...
];
This helps a lot on unit testing and reusability of packages.

AngularJS: How to have different Services/Controllers in same Module?

I have a Service and a controller in my AngularJS App, that should be in the same module, but are two different files:
// File 1 (Service)
angular.module('myService', ['ngRoute'])
.service('myService', // ...
// File 2 (Controller)
angular.module('myController', ['ngRoute'])
.controller('myController', // ..
This works fine. Now I want to have Service & Controller in one Module so I can load just one instead of two Modules. So I change the first line (of both files) to:
// Change in both files:
angular.module('myModule', ['ngRoute'])
But now I get an error:
Error: [$injector:unpr] ...
Maybe somebody knows, what could be wrong here. Thank you very much!
You can do the following:
var myApp = angular.module('myApp', []);
myApp.controller("myService"
myApp.service("myApp")
Or
angular.module("myModule").controller
angular.module("myModule").service
If you use angular.module('myService', []) twice, you are initializing the same module twice.
If you just use angular.module("myModule"), without the dependencies, you are just calling it.
You have two options -
use a variable as mentioned by Michael
OR
Use it like -
// Initialize myService Module in any JS file
(make sure this file is included before File 1 and File 2
angular.module('myService', ['ngRoute']);
// File 1 (Service)
angular.module('myService').service('myService', // ...
// File 2 (Controller)
angular.module('myService').controller('myController', // ..

Adding new Module is not working in angularjs

i am trying to add a new Module to my application.
My HTML for index page is
<body ng-app="com.app">
In my app.js
angular.module('mod1', ['ngResource']);
angular.module('mod2', []); //this is module i want to add
var app = angular.module('com.app', ['ngResource','mod1','mod2']);
My Controllers1.js
var Controllers = angular.module('mod1');
Controllers.controller('ctrl1', function($scope,$http) {});
Controllers.controller('ctrl2', function($scope,$http) {}); //function for module 2
when i try to add this ctrl2 to my "controllers1.js" it works , but if i add this in my other js say "controllers2.js", its not working .
My controllers2.js is
'use strict';
var mymodule = angular.module('mod2');
mymodule.controller('ctrl2', function() {
console.debug("Testing...");
});
summary of my question is : when i try to add my ctrl2 function to new module, its not working and on firefox console i am getting error
Error: Argument 'ctrl2' is not a function, got undefined
assertArg#http://localhost:8080/tm-webapp/resources/lib/angular.js:1039
assertArgFn#http://localhost:8080/tm-webapp/resources/lib/angular.js:1050
#http://localhost:8080/tm-webapp/resources/lib/angular.js:4802
update#http://localhost:8080/tm-webapp/resources/lib/angular.js:14198
Scope.prototype.$broadcast#http://localhost:8080/tm-webapp/resources/lib/angular.js:8307
updateRoute/<#http://localhost:8080/tm-webapp/resources/lib/angular.js:7463
qFactory/defer/deferred.promise.then/wrappedCallback#http://localhost:8080/tm-webapp/resources/lib/angular.js:6846
qFactory/defer/deferred.promise.then/wrappedCallback#http://localhost:8080/tm-webapp/resources/lib/angular.js:6846
qFactory/ref/<.then/<#http://localhost:8080/tm-webapp/resources/lib/angular.js:6883
Scope.prototype.$eval#http://localhost:8080/tm-webapp/resources/lib/angular.js:8057
Scope.prototype.$digest#http://localhost:8080/tm-webapp/resources/lib/angular.js:7922
Scope.prototype.$apply#http://localhost:8080/tm-webapp/resources/lib/angular.js:8143
done#http://localhost:8080/tm-webapp/resources/lib/angular.js:9170
completeRequest#http://localhost:8080/tm-webapp/resources/lib/angular.js:9333
createHttpBackend/</xhr.onreadystatechange#http://localhost:8080/tm-webapp/resources/lib/angular.js:9304
I am stuck here for a long, kindly help me i shall be very thankful.
Regards,
Make sure that in your file loader (script tags, requirejs, whatever) Controllers1.js is right next to controllers2.js.
PS: some operating systems / webservers (e.g. the server inside karma on windows) are case sensitive. So try to use same case for your files (either upper or lower).
You can try this plunker http://plnkr.co/edit/tKIPDQ54JDexB7LAJpDR to see if it works in the way you want.

syncing the views of two angular apps

I have two angular applications in one page, and I need them to communicate. Specifically, I want one application to use a service of another application.
I am able to get the service of the other application using Injector.get(service), but when I change the data using the service in one application, it does not reflect in the view of the other, even though both are supposed to show the same data. You can see a simplified version of the problem in jsFiddle.
To save you the click, this is the relevant script:
//myAppLeft - an angular app with controller and service
var myAppLeft = angular.module('myAppLeft', []);
myAppLeft.factory('Service1',function(){
var serviceInstance = {};
serviceInstance.data = ['a','b','c','d','e'];
serviceInstance.remove = function(){
serviceInstance.data.pop();
console.log(serviceInstance.data);
};
return serviceInstance;
} );
myAppLeft.controller('Ctrl1', ['$scope', 'Service1', function($scope, service1) {
$scope.data = service1.data;
$scope.changeData =function(){
service1.remove();
}
}]);
var leftAppInjector = angular.bootstrap($("#leftPanel"), ['myAppLeft']);
//myAppRight = an angular app with controller which uses a service from myAppLeft
var myAppRight = angular.module('myAppRight', []);
myAppRight.controller('Ctrl2', ['$scope', function($scope) {
$scope.data = leftAppInjector.get('Service1').data;
$scope.changeData =function(){
leftAppInjector.get('Service1').remove();
}
}]);
var rightAppInjector = angular.bootstrap($("#rightPanel"), ['myAppRight']);
I'd be happy to know why my code does not work as expected, and would be even happier to know if and how such thing can work.
I understand that if instead of two angular-apps I would have used one angular-app with two modules this would have worked just as I wanted, but unfortunately I cannot adopt this approach because my application consists of a pure-js core with extensions, each extension can be written in a different library/platform and I want my extensions to be angular ones.
Thanks,
Nurit.
Angular apps are separate entities, even if you use the same service in both. the second app just initializes its own version off it.
What you want can be done using localStorage, and the storage events.
Ping me if you need additional help on this!

Resources