AngularJS: Share factory between multiple modules - javascript

Let's say I have a module called App which injects two other modules called factories and controllers:
var app = angular.module("app", ["factories", "controllers", "directives"])
.run(function ($rootScope, userFactory) {
userFactory.property = "someKickstartValue";
});
The factories module holds all factories:
var factories = angular.module("factories", []),
factory = factories.factory("testFactory", {
property: "someValue"
});
And the controllers module holds all controllers:
var controllers = angular.module("controllers", ["factories"]),
controller = controllers.controller("controller", function ($scope, testFactory) {
console.log(testFactory.property); // Returns "Some Value" and not
// "someKickstartValue" as expected.
});
The actual Question:
Why does the "someKickstartValue" not apply to the controllers? As far as I do understand the module app has it's own testFactory instance and the module controllers has it's own as well, so there can't be any information shared between modules via factories. Is there a way around, or have I made a mistake?

I fixed it by removing the "factories" dependency of the controller.
var controllers = angular.module("controllers", []),
controller = controllers.controller("controller", function ($scope, testFactory) {
console.log(testFactory.property); // Returns "someKickstartValue" as expected
});
Because I now do not declare factories as dependency, the controllers module doesn't create it's own instance of factories and has access to the instance of the app module which injects the controllers module.

I faced the same problem. I solved it in the following way:
// modules.js
(function (angular) {
angular.module("shared", []);
angular.module("user", ["shared"]);
angular.module("admin", ["shared"]);
})(window.angular);
Such structure allows to use factories, services, directives attached to the shared module in other modules.

Related

Why is my Angularjs Service not allowing me to call it?

I'm trying to make an Angular Service that houses common functions.
I bundled the code within my MVC app:
bundles.Add(new ScriptBundle("~/bundles/Angular")
.IncludeDirectory("~/app", "*.js", true));
And I checked in Developer Tools if it actually brought in my Common Folder with Common.js :
I added Common to the App :
var app = angular.module('app',
[
'JobCtrl',
'JobSvc',
'WebsiteCtrl',
'WebsiteSvc',
'myClientCtrl',
'ClientSvc',
'MediaCompanyCtrl',
'MediaCompanySvc',
'PageAlertSvc',
'ui.bootstrap',
'ui.bootstrap.tpls',
'Common'
]
);
and to the Controller:
angular.module('app', ['ui.bootstrap', 'ui.bootstrap.tpls'])
.controller('JobCtrl',
[
'JobService',
'WebsiteService',
'MediaCompanyService',
'ProductService',
'$scope',
'$uibModal',
'PageAlertService',
'Common',
function (JobService, WebsiteService, MediaCompanyService,
ProductService, $scope, $uibModal,PageAlertService, Common)
This is what my Common.js file looks like:
angular.module('app')
.service('Common', function () {
this.heyThere = function ()
{
console.log('Just wanted to say hey there')
};
});
Whenever it is called within my JobCtrl I get a Error: $injector:unpr
Unknown Provider.
Could anyone see what I may be doing wrong where it won't recognize my Common.js file? When I move Common.js to the Services folder and try calling it within my controller it works, but not when it is in my Common Folder. Makes no sense!
Thanks in advance!
That is simply because you are defining your app..twice!!!!
angular.module('app', []) // this is where you re-define your app
.service('Common', function () {
this.heyThere = function ()
{
console.log('Just wanted to say hey there')
};
});
should be:
angular.module('app')
.service('Common', function () {
this.heyThere = function ()
{
console.log('Just wanted to say hey there')
};
});
the module function has 2 modes.. with 2 arguments you are setting up your app.. with a single argument you just getting a reference to an existing app (which is already defined before that)
Please be careful when you use the declaration of a module. You are basically reassigning the app module to different instances.
angular.module('app', [dependencies]) //Constructs a module with dependencies
angular.module('app').service(...) //Associates the components (service)
//with the app module.

inject $rootScope in config angularJs

I have problem to inject $rootScope in config angularJS, this is my code, but still error, maybe anyone help me how to inject $rootScope in config angularJS. .
thanks.
(function() {
'use strict';
angular
.module('uliappApp')
.directive('angular-loading-bar', ['cfpLoadingBarProvider'])
.config(cfpLoadingBarProvider);
cfpLoadingBarProvider.$inject = ['cfpLoadingBarProvider', '$rootScope'];
function cfpLoadingBarProvider(cfpLoadingBarProvider, $rootScope) {
cfpLoadingBarProvider.includeBackdrop = true;
console.log(rootScope.concessionLoadingScreen);
cfpLoadingBarProvider.spinnerTemplate = '<div class="loading-bar-container">'
+ '<div id="loading-bar-spinner"><div class="spinner-icon"></div></div></div>';
}
})();
You don't need rootScope in configuration phase, it can be simply achieved by using .run().
angular
.module('uliappApp')
.run(['$rootScope', function($rootScope){
$rootScope.concessionLoadingScreen = true;
}])
During the config phase, only providers can be injected.
Basically angularjs first invoke the config method and then invoke the run method. During config only providers are available. A provider can then be used to create service instance. So, you can use .run to inject $rootScope.
For example, the following is not allowed:
myMod.config(function(greeting) {
// WON'T WORK -- greeting is an *instance* of a service.
// Only providers for services can be injected in config blocks.
});
What you do have access to are any providers for services you've made:
myMod.config(function(greetingProvider) {
// ok fine!
});
All the best.
You can not use $rootScope during the configuration phase of an angular application.
Only constant and provider can be injected to the configuration phase.
You can use run phase, or create a provider (that is actually a service) to hold the configuration you want.
// Option 1 - during run
angular
.module('yourApp')
.run(['$rootScope', function($rootScope) {
}])
// Option 2 - provider
angular
.module('yourApp')
.provider('yourSettings', function() {
var $this = this;
this.yourSettings = 'yourValue';
this.$get = function() {
return $this;
}
})
angular
.module('yourApp')
.config(['yourSettingsProvider', function(yourSettingsProvider) {
// You can use yourSettingsProvider.yourSettings
}])

Calling module constant?

I have the following Angular module. How can i call for example APIHost from one of my controllers?
angular.module('configuration', [])
.constant('APIHost','http://api.com')
.constant('HostUrl','http://example.com')
.constant('SolutionName', 'MySite');
Constant is nothing but one kind of provider recipe.
You need to inject constant dependency inside your controller factory function, that's it.
app.controller('testCtrl', function($scope, APIHost){
console.log(APIHost)
})
Make sure your configuration module has been added to main module as dependency
to get use of constant's provider like below
var app = angular.module('app', ['configuration', 'otherdependency']);
app.controller( ... ) //here you can have configuration constant available
Like this, just like any service or factory.
I have also include structure for industry standard (kind of) from john papa's coding guidelines.
(function() {
'use strict';
angular
.module('configuration')
.controller('ctrlXYZ', ctrlXYZ);
//Just inject as you would inject a service or factory
ctrlXYZ.$inject = ['APIHost'];
/* #ngInject */
function ctrlXYZ(APIHost) {
var vm = this;
activate();
function activate() {
//Go crazy with APIHost
console.log(APIHost);
}
}
})();
Hope the helps!

Angularjs - Inject factory without reference

I have the following code:
main.js
angular.controller('myCtrl', function($scope, $rootScope) {
$scope.name = "Bob";
}
myservices.js
angular.factory('myService', function($http) {
var myService = {
async: function(params) {
// $http returns a promise, which has a then function, which also returns a promise
var promise = $http.get("http://myws/user/info/"+params).then(function (response) {
// The then function here is an opportunity to modify the response
console.log(response);
// The return value gets picked up by the then in the controller.
return response.data;
});
// Return the promise to the controller
return promise;
}
};
return myService;
});
How can inject myService in myCtrl ? considering they are in two separated files.
We need to add in order all of our scripts we have created to run this angular, take note the order:
<script src="angular.js"></script>
<script src="main.js"></script>
<script src="myservices.js"></script>
main.js should look like:
var app = angular.module("MyModule", []);
app.controller('myCtrl', function($scope, $rootScope, myService) { /* implementation */})
services.js should look like:
app.factory('myService', function($http) { /* implementation */});
So in our main.js we are creating a module to attach all of our services, factories, providers, values, constants, controllers and directives. It also allows us to put the config and run phase functions in.
The module is instantiated via:
angular.module("MyModule", []);
We're providing a second argument of other dependant modules
If we needed to, we could ask angular for the module again, in the case of use javascript modules:
var app = angular.module("MyModule");
Below are several thing you need to do.
Should be they should belong same/different angular module(if its different module then you have inject into main module to use it).
You need to use angular.module('myApp') to bind components to it, so that the service will be available in that module.
Code
//app.js
angular.module('myApp', ['myApp.service']); //this should be module definition somewhere
//service.js
angular.module('myApp.service', [])
angular.module('myApp.service').factory('myService', function($http) {
//service code
});
//controller.js
angular.module('myApp').controller('myCtrl', function($scope, $rootScope, myService) {
console.log(myService); //service instance here
$scope.name = "Bob";
}
you can inject service in your controller
like:
main.js:
angular.module('myApp', []).controller('myController', ['$scope', 'myService',
function ($scope, myService) {
}
]);
myService.js:
angular.module('myApp').factory('myService', function($http) {
//service code
});
for different file but same module then ensure that file is loaded before use.
Make sure the files are both actually loaded. How to do that is up to you, perhaps you're using some implementation of require(), or you simply list all the files in your HTML as <script> tags.
Clarify what module structure you want to have. Should both be part of the same module, or should they be separate modules?
Same module: One file needs to declare the module, the other needs to extend it:
angular.module('Foo', []) // declares new module
.controller(..)
angular.module('Foo') // extends existing module
.factory(..)
Different modules:
angular.module('Foo', []) // declares new module
.factory(..)
angular.module('Bar', ['Foo']) // declares new module
.controller(..) // and imports other module
Inject into the controller:
.controller('myCtrl', function ($scope, myService) ..

How to test function in $scope from different controller?

I'm using Jasmine for testing my AngularJS application. I have an Authenticaiton controller, which calls a function which I define in the scope from the Application controller. So:
1. AppController
$scope.setUser = function() {}
2. AuthenticationController
$scope.setUser(User);
I am testing the AuthenticationController, and setUser() is not inside the scope of AuthenticationController. How do I inject the scope/function from the AppController?
The error message:
TypeError: $scope.setUser is not a function
Should I mock the whole function? Is the structure smelly? What's the best way to do this?
EDIT:
In the real app, AuthenticationController gets injected into my dashboard-app.
AuthenticationController:
angular
.module( 'authentication', [])
.controller('AuthenticationController', AuthenticationController);
AuthenticationController.$inject = ['$scope', '$rootScope', 'AUTH_EVENTS', 'AuthenticationService'];
Dashboard:
angular
.module('dashboard', [
'authentication'
])
.run(run);
Info: Names are changed in my question to make it easier to understand.
inject $rootScope into your controllers.
AppController :
$rootScope.setUser = function() {}
AuthenticationController
$rootScope.setUser();

Categories