Is Angular service really singleton? - angularjs

I have an Angular service like this:
angular.module('MyModule')
.factory('SharedData', function( ){
return {
session_id: undefined,
getSessionId: function () {
return this.session_id;
},
setSessionId: function (new_id) {
this.session_id = new_id;
},
};
}).
controller( 'MyController', ['SharedData', function( SharedData ){
console.log( "Retrieved session id = " + SharedData.getSessionId());
// getting undefined here!
}]);
I called the service at an earlier time in another module like this:
angular.module( 'bootstrapper' )
factory("AnotherService", function(){
var injector = angular.injector(['MyModule', 'ng']),
shared_data = injector.get('SharedData');
shared_data.setSessionId( getUrlParameter('SESSIONID'));
...
});
The console output result is undefined.
I think the SharedData in 'MyController' and the SharedData in 'AnotherService' are not the same object. However, people are all saying that Angular services are singletons. Are they real singletons?
More details about my modules:
I used module 'bootstrapper' to manually bootstrap the other module 'MyModule':
angular.module( 'bootstrapper' )
.run(function () {
angular.bootstrap(document, ['MyModule']);
});

angular.factory are not constructors, it seems to me that using angular.service instead would solve your problem,

You can provide constants to the app at bootstrap time as a module dependency.
angular.module( 'bootstrapper' )
.config(function () {
var sessionIdProvider = function ($provide) {
$provide.constant("SESSIONID", getUrlParameter('SESSIONID'));
};
angular.bootstrap(document, ['MyModule', sessionIDProvider]);
});
For more information see the AngularJS $provide Service API Reference -- constant.
Update
You can also skip the bootstrap app and use a config block in the MyModule app.
angular.module( 'MyModule' )
.config(function ($provide) {
$provide.constant("SESSIONID", getUrlParameter('SESSIONID'));
});
For more information see the AngularJS angular.module API Reference,

After thinking a bit, I feel that you have chosen not very good approach. It's better to define bootstrapper application and make it initialize sharedData service, then share it with other dependent modules. Note, not applications like in your case, but dependent modules. This would be much simpler and cleaner.
Here is an example setup that would allow nice "modularization":
/**
* Bootstrapper application.
*/
angular.module('bootstrapper', ['dashboard'])
.factory('sharedData', function() {
return {
sessionId: undefined,
setSessionId: function(value) {
this.sessionId = value;
},
getSessionId: function() {
return this.sessionId;
}
}
})
.controller('BootController', function(sharedData) {
this.name = 'Bootstrapper app';
sharedData.setSessionId('34sd-3sdf345g-23a2421b');
});
/**
* Apllication kicked off by main bootstrapper.
*/
angular.module('dashboard', [])
.directive('dashboardModule', function() {
return {
controller: 'DashboardController as dashboard',
template:
"<div>" +
" {{ dashboard.name }} sessionId: {{ dashboard.sharedData.sessionId }}" +
"</div>"
};
})
.controller('DashboardController', function(sharedData) {
this.name = 'Dashboard';
this.sharedData = sharedData;
});
<script src="https://code.angularjs.org/1.4.8/angular.js"></script>
<body ng-app="bootstrapper" ng-controller="BootController as boot">
<h3>{{ boot.name }}</h3>
<dashboard-module name="dashboard"></dashboard-module>
<!-- <some-other-module></some-other-module> -->
</body>

Related

How can i provide a .config function to configure my library

I have made a little library of code for angular js. I have created a .config method in my library's main module that depends on my moduleConfigProvider. I expect the consumer of my library to call .configure on my config provider during the app.config stage (asap on app start).
The problem is that my .config in my module seems to run BEFORE the app.config of the main app module. How can I work around this problem?
e.g. This is how i'm consuming the config. I need to consume it during the .config stage because I need to configure things like $httpProvider.
// this module provides initial configuration data for module
angular.module('mymodule')
.config(['$httpProvider', 'someOptionsProvider', 'myConfigProvider',
function ($httpProvider, someOptionsProvider, myConfigProvider) {
console.log("Consuming config now: ", myConfigProvider.config);
}])
Here is the config provider:
angular.module('mymodule.config')
.provider('myConfig', function() {
var _this = this;
_this.configure = configureMethod;
_this.config = {};
function configureMethod(configData) {
_this.config = configData;
console.log("Config set to:", configData);
};
this.$get = function() {
return _this;
};
});
And finally here is my app.config:
angular.module('app')
.config(['myConfigProvider', function(myConfigProvider) {
console.log("Running App config:", myConfigProvider);
var config = { a: 1 };
console.log("Config ready to send:", config);
myConfigProvider.configure(config);
}])
;
Okay, it is simple, just use other providers in your provider function as dependencies.
Check the following snippet
angular.module('mymodule', [])
.provider('myConfig', [
'$httpProvider',
function($httpProvider) {
var _this = this;
_this.configure = configureMethod;
_this.config = {};
function configureMethod(configData) {
//Do here anything with the $httpProvider
_this.config = configData;
console.log("Config set to:", configData);
console.log('Configuring $httpProvider')
};
this.$get = function() {
return _this;
};
}
])
angular.module('app', ['mymodule'])
.config(['myConfigProvider', function(myConfigProvider) {
console.log("Running App config:");
var config = {
a: 1
};
console.log("Config ready to send:", config);
myConfigProvider.configure(config);
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
</div>

AngularJS shared REST service between modules and controllers

I need to have a set of resource factories to consume a rest api and use that in all of my modules and controllers. I'm confused as to how this should be separated and how to access the factories from controller.
As an example, let's assume I have:
// rest.js
angular.module('myApp.rest', ['ngResource'] )
.factory('Book', function ($resource) {
return $resource('api/book', {}, {
getBook: {
method: 'GET'
},
});
})
Here's the main module as myApp:
// app.js
angular.module('myApp', [
'ngRoute',
'ngResource',
'app.rest',
'app.library'
])
.config(['$routeProvider', function ($routeProvider) {
$routeProvider.
when('/book', {
templateUrl: 'someTemplate',
controller: 'LibraryCTRL',
});
Now I want to have another module called app.library which can use Book resource. How the Dependency Injection would look like?
More important question: Is this the right way to do it? I mean is it better to attach the whole Book factory to myApp or use a separate myApp.rest module?
// library.js
angular
.module('myApp.library', ['ngResource']) // INJECT REST MODULE HERE?
.controller('LibraryCtrl', Library);
// INJECT BOOK RESOURCE HERE?
Library.$inject = [];
// USE BOOK IN THIS CONSTRUCTOR
function Library() {
var vm = this;
// USING IT
Book.getBook(function(data){
vm.book = data;
});
}
let's Abstract the problem
as i understand you want to make custom factory "service" which can be used in all modules and controllers that is responsible for consuming rest api
so you will have serviceModule.js
var ServiceApp = angular.module('ServiceApp', []);
ServiceApp
.factory(
'restControllerService',
[
'$http',
function($http) {
var doRequest =
function(URL) {
return $http({
method : 'get',
url : URL,
headers : {
'Content-Type' :'application/json'
}
});
});
}
}
return {
getBook : function() {
return doRequest('api/book');
}
};
} ]);
you can inject that in any other module like that
var library = angular.module('libraryModule', [ "ServiceApp" ]);
libraryModule.controller('LibraryCtrl', [
'$scope',
'restControllerService',
function($scope,restControllerService) {
$scope.book = null;
$scope.getbook = function() {
restControllerService.getbook('api/book').success(
function(data) {
$scope.book = data;
}).error(function() {
$scope.book = null;
});
}
};
I believe you're trying to do this:
myApp --> myApp.library --> myApp.rest
You're pretty much there. Just make myApp.library inject the myApp.rest module.
angular
.module('myApp.library', ['myApp.rest'])
.controller('LibraryCtrl', ['Book', function(Book) {
// use Book.getBook() here.
}]);
Also remove the dependency of myApp.rest and ngResource from myApp module, since you're not using them there.
angular.module('myApp', [
'ngRoute',
'app.library'
])
In general, only add a dependency if you're directly using it in that module.
I don't believe there is a best practice for how to separate code into modules. Personally, I like to have a single module for an entire application, unless I'm trying to reuse a piece of code in another application.

AngularJS Inject factory into another factory from the same module

I'm trying to inject the factory Application into the ApplicationService factory. Both are defined in the same module.
Application factory (application.model.js)
(function(Object, coreModule) {
'use strict';
// the factory to expose that allows the creation of application instances
var ApplicationFactory = function() {
console.log("Application factory!");
return {foo: 'bar'};
}
coreModule.factory('Application', [ApplicationFactory]);
})(Object, angular.module('core'));
ApplicationService factory (application.service.js)
(function(coreModule) {
'use strict';
var ApplicationService = function(Application) {
var api = {
shout = function() {console.log(Application);}
};
return api;
}
ApplicationService.$inject = ['Application'];
coreModule.factory('ApplicationService', [ApplicationService]);
})(angular.module('core'));
Then I'm injecting ApplicationService factory into a controller and calling the method shout. I get undefined when in the console's log, Application is always undefined. If in a controller I innject Application it works. So i know both factories are working standalone.
Both files are being imported in my index.html.
I've spent hours looking for the issue but I can't find it. What am I doing wrong?
Please see working demo below.
You've got 2 options.
a) Remove square brackets here:
coreModule.factory('ApplicationService', ApplicationService)
b) Add injected Application as first element before ApplicationService:
coreModule.factory('ApplicationService', ['Application', ApplicationService])
var app = angular.module('core', []);
app.controller('firstCtrl', function($scope, ApplicationService) {
ApplicationService.shout();
});
(function(Object, coreModule) {
'use strict';
// the factory to expose that allows the creation of application instances
var ApplicationFactory = function() {
console.log("Application factory!");
return {
foo: 'bar'
};
};
coreModule.factory('Application', [ApplicationFactory]);
})(Object, angular.module('core'));
(function(coreModule) {
'use strict';
var ApplicationService = function(Application) {
var api = {
shout: function() {
console.log(Application);
}
};
return api;
};
ApplicationService.$inject = ['Application'];
coreModule.factory('ApplicationService', ApplicationService);
})(angular.module('core'));
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="core">
<div ng-controller="firstCtrl">
</div>
</body>

Best way to save and use config settings in AngularJS

I'm new to AngularJS and just building an app to learn it. My app calls a REST API and right now I have the hostname hard coded in the app. I want to make this in app setting (and maybe later have somewhere to configure it). I thought I'd start with a constant. Should it go in my app.js like this? If so, I'm not sure of the syntax for adding it to the .config settings with $routeProvider there too
(function () {
// Define module and add dependencies inside []
var app = angular.module("haClient", ["ngRoute"]);
app.constant('hostname', 'http://192.192.192.192:8176');
app.config(function ($routeProvider) {
$routeProvider
// Register routes
// Main route
.when("/main", {
templateUrl: "main.html",
controller: "MainController"//,
//activeTab: 'home'
})
// Device List
.when("/devices", {
templateUrl: "devicelist.html",
controller: "DeviceListController"
})
// Device details (param is device name)
.when("/device/:devicename", {
templateUrl: "device.html",
controller: "DeviceController"
})
// Invalid URL's get sent back to main route
.otherwise({ redirectTo: "/main" });
}); // End App Config
}());
This is the module that needs to use it (called from controllers):
(function () {
var deviceCtrl = function ($http) {
var getDevices = function () {
return $http.get("http://192.192.192.192:8176/devices.json/")
.then(function (response) {
return response.data;
});
};
// get details and return a promise
var getDeviceDetails = function (deviceName) {
return $http.get("http://192.192.192.192:8176/devices/" + deviceName + ".json/")
.then(function (response) {
return response.data;
});
};
// Public API
return {
getDeviceDetails: getDeviceDetails,
getDevices: getDevices
};
};
var module = angular.module("haClient");
}());
Can someone enlighten em on the best way to set it and get it?
Thanks
I currently do this by using templates to build the root .html file in the backend. Eg, using doT templates in node.js, I put this below my other js includes:
<!-- load any templated constants -->
<script>
angular.module('mymod').constant('globals', {
api: '{{=it.api}}'
});
</script>
This way my backend can work out the logic of where the client needs to point to. In order to use the value in another service or controller, you simply inject the constant by name:
angular.module('somemod', []).factory('myservice', ['globals', function(globals){
// use globals.api or what ever you set here for example
}]);
The best place to do configuration is in a Provider and inside your config block.
Providers expose an API that allows you to configure your service before it's injected into your controllers and directives.
Suppose you have a service called myService that you want injected into your controller function like this:
app.controller('ctrl', function($scope, myService) { ...});
And myService is responsible for retrieving data through web API calls. Let's further assume that you would like to configure your service with the root URL htt://servername/, since all calls will share the same host name.
You can define your myServiceProvider like this:
app.provider('myService', function(){
var webapiurl;
this.setWebServiceUrl = function (url) {
webapiurl = url;
}
// the injector will call the $get function to create the singleton service that will be injected
this.$get = function( /*injectables*/) {
return {
getData: function() {... Use webapiurl ...}
}
}
});
Then in your config function, configure your provider:
app.config(function(myServiceProvider){
myServiceProvider.setWebServiceUrl('htt://servername');
});
Finally you can inject the service anywhere it can be injected:
app.controller('ctrl', function($scope, myService) {
$scope.data = myService.getData();
});
I couldn't get the supplied answers to work (no reason to think they wouldn't). here's what I did.
My main app.js (constants section)
(function () {
// Define module and add dependencies inside []
var app = angular.module("haClient", ["ngRoute"]);
//constants
app.constant('mySettings', {
baseURL: 'http://192.192.192.192:8176',
otherSetting: 'XYZ'
});
app.config(function ($routeProvider) {
$routeProvider
// Register routes
// Main route
.when("/main", {
templateUrl: "main.html",
controller: "MainController"//,
//activeTab: 'home'
})
// Device List
.when("/devices", {
templateUrl: "devicelist.html",
controller: "DeviceListController"
})
// Device details (param is device name)
.when("/device/:devicename", {
templateUrl: "device.html",
controller: "DeviceController"
})
// Invalid URL's get sent back to main route
.otherwise({ redirectTo: "/main" });
}); // End App Config
}());
In my service (added mySettings as a dependency and then just used mySettings.baseURL):
(function () {
var deviceCtrl = function ($http, $log, mySettings) {
$log.info("DeviceCtrl - baseURL: " + mySettings.baseURL);
// get device list and return a promise
var getDevices = function () {
return $http.get(mySettings.baseURL + "/devices.json")
.then(function (response) {
return response.data;
});
};
// get details and return a promise
var getDeviceDetails = function (deviceName) {
$log.info("DeviceCtrl - Getting device info for " + deviceName);
return $http.get(mySettings.baseURL + "/devices/" + deviceName + ".json")
.then(function (response) {
return response.data;
});
};
// Public API
return {
getDeviceDetails: getDeviceDetails,
getDevices: getDevices
};
};
var module = angular.module("haClient");
module.factory("deviceCtrl", deviceCtrl);
}());
I'm certainly no expert (as is clear from not being able to get supplied answers working), and I'm not sure (yet) if there are any drawbacks to this method. It allowed me to get on with my project and learn more of Angular, so I went with it.
Regards
Mark
I have used another module and injected it into app module like this
Create constant.js and include that in your index.html & add following code inside that
angular.module('constantsModule', []).constant('BASEURL', 'http://google.com');
Inside app.js, inject 'constantsModule' so that all constants inside it will be available for 'haClient'
angular.module('haClient', [
'constantsModule'
])
.config(function ($routeProvider) {
.when('/', {
templateUrl: 'views/landing.html',
controller: 'landingCtrl'
})
});
Inside landingCtrl, since its in scope of 'haClient', we can inject BASEURL constant from 'constantsModule'
angular.module('haClient').controller('landingCtrl', function ($scope, BASEURL) {
// just to show, how to access it inside controller
$scope.baseurl = BASEURL;
});

Inject service in app.config

I want to inject a service into app.config, so that data can be retrieved before the controller is called. I tried it like this:
Service:
app.service('dbService', function() {
return {
getData: function($q, $http) {
var defer = $q.defer();
$http.get('db.php/score/getData').success(function(data) {
defer.resolve(data);
});
return defer.promise;
}
};
});
Config:
app.config(function ($routeProvider, dbService) {
$routeProvider
.when('/',
{
templateUrl: "partials/editor.html",
controller: "AppCtrl",
resolve: {
data: dbService.getData(),
}
})
});
But I get this error:
Error: Unknown provider: dbService from EditorApp
How to correct setup and inject this service?
Set up your service as a custom AngularJS Provider
Despite what the Accepted answer says, you actually CAN do what you were intending to do, but you need to set it up as a configurable provider, so that it's available as a service during the configuration phase.. First, change your Service to a provider as shown below. The key difference here is that after setting the value of defer, you set the defer.promise property to the promise object returned by $http.get:
Provider Service: (provider: service recipe)
app.provider('dbService', function dbServiceProvider() {
//the provider recipe for services require you specify a $get function
this.$get= ['dbhost',function dbServiceFactory(dbhost){
// return the factory as a provider
// that is available during the configuration phase
return new DbService(dbhost);
}]
});
function DbService(dbhost){
var status;
this.setUrl = function(url){
dbhost = url;
}
this.getData = function($http) {
return $http.get(dbhost+'db.php/score/getData')
.success(function(data){
// handle any special stuff here, I would suggest the following:
status = 'ok';
status.data = data;
})
.error(function(message){
status = 'error';
status.message = message;
})
.then(function(){
// now we return an object with data or information about error
// for special handling inside your application configuration
return status;
})
}
}
Now, you have a configurable custom Provider, you just need to inject it. Key difference here being the missing "Provider on your injectable".
config:
app.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: "partials/editor.html",
controller: "AppCtrl",
resolve: {
dbData: function(DbService, $http) {
/*
*dbServiceProvider returns a dbService instance to your app whenever
* needed, and this instance is setup internally with a promise,
* so you don't need to worry about $q and all that
*/
return DbService('http://dbhost.com').getData();
}
}
})
});
use resolved data in your appCtrl
app.controller('appCtrl',function(dbData, DbService){
$scope.dbData = dbData;
// You can also create and use another instance of the dbService here...
// to do whatever you programmed it to do, by adding functions inside the
// constructor DbService(), the following assumes you added
// a rmUser(userObj) function in the factory
$scope.removeDbUser = function(user){
DbService.rmUser(user);
}
})
Possible Alternatives
The following alternative is a similar approach, but allows definition to occur within the .config, encapsulating the service to within the specific module in the context of your app. Choose the method that right for you. Also see below for notes on a 3rd alternative and helpful links to help you get the hang of all these things
app.config(function($routeProvider, $provide) {
$provide.service('dbService',function(){})
//set up your service inside the module's config.
$routeProvider
.when('/', {
templateUrl: "partials/editor.html",
controller: "AppCtrl",
resolve: {
data:
}
})
});
A few helpful Resources
John Lindquist has an excellent 5 minute explanation and demonstration of this at egghead.io, and it's one of the free lessons! I basically modified his demonstration by making it $http specific in the context of this request
View the AngularJS Developer guide on Providers
There is also an excellent explanation about factory/service/provider at clevertech.biz.
The provider gives you a bit more configuration over the .service method, which makes it better as an application level provider, but you could also encapsulate this within the config object itself by injecting $provide into config like so:
Alex provided the correct reason for not being able to do what you're trying to do, so +1. But you are encountering this issue because you're not quite using resolves how they're designed.
resolve takes either the string of a service or a function returning a value to be injected. Since you're doing the latter, you need to pass in an actual function:
resolve: {
data: function (dbService) {
return dbService.getData();
}
}
When the framework goes to resolve data, it will inject the dbService into the function so you can freely use it. You don't need to inject into the config block at all to accomplish this.
Bon appetit!
Short answer: you can't. AngularJS won't allow you to inject services into the config because it can't be sure they have been loaded correctly.
See this question and answer:
AngularJS dependency injection of value inside of module.config
A module is a collection of configuration and run blocks which get
applied to the application during the bootstrap process. In its
simplest form the module consist of collection of two kinds of blocks:
Configuration blocks - get executed during the provider registrations and configuration phase. Only providers and constants
can be injected into configuration blocks. This is to prevent
accidental instantiation of services before they have been fully
configured.
I don't think you're supposed to be able to do this, but I have successfully injected a service into a config block. (AngularJS v1.0.7)
angular.module('dogmaService', [])
.factory('dogmaCacheBuster', [
function() {
return function(path) {
return path + '?_=' + Date.now();
};
}
]);
angular.module('touch', [
'dogmaForm',
'dogmaValidate',
'dogmaPresentation',
'dogmaController',
'dogmaService',
])
.config([
'$routeProvider',
'dogmaCacheBusterProvider',
function($routeProvider, cacheBuster) {
var bust = cacheBuster.$get[0]();
$routeProvider
.when('/', {
templateUrl: bust('touch/customer'),
controller: 'CustomerCtrl'
})
.when('/screen2', {
templateUrl: bust('touch/screen2'),
controller: 'Screen2Ctrl'
})
.otherwise({
redirectTo: bust('/')
});
}
]);
angular.module('dogmaController', [])
.controller('CustomerCtrl', [
'$scope',
'$http',
'$location',
'dogmaCacheBuster',
function($scope, $http, $location, cacheBuster) {
$scope.submit = function() {
$.ajax({
url: cacheBuster('/customers'), //server script to process data
type: 'POST',
//Ajax events
// Form data
data: formData,
//Options to tell JQuery not to process data or worry about content-type
cache: false,
contentType: false,
processData: false,
success: function() {
$location
.path('/screen2');
$scope.$$phase || $scope.$apply();
}
});
};
}
]);
You can use $inject service to inject a service in you config
app.config(function($provide){
$provide.decorator("$exceptionHandler", function($delegate, $injector){
return function(exception, cause){
var $rootScope = $injector.get("$rootScope");
$rootScope.addError({message:"Exception", reason:exception});
$delegate(exception, cause);
};
});
});
Source: http://odetocode.com/blogs/scott/archive/2014/04/21/better-error-handling-in-angularjs.aspx
** Explicitly request services from other modules using angular.injector **
Just to elaborate on kim3er's answer, you can provide services, factories, etc without changing them to providers, as long as they are included in other modules...
However, I'm not sure if the *Provider (which is made internally by angular after it processes a service, or factory) will always be available (it may depend on what else loaded first), as angular lazily loads modules.
Note that if you want to re-inject the values that they should be treated as constants.
Here's a more explicit, and probably more reliable way to do it + a working plunker
var base = angular.module('myAppBaseModule', [])
base.factory('Foo', function() {
console.log("Foo");
var Foo = function(name) { this.name = name; };
Foo.prototype.hello = function() {
return "Hello from factory instance " + this.name;
}
return Foo;
})
base.service('serviceFoo', function() {
this.hello = function() {
return "Service says hello";
}
return this;
});
var app = angular.module('appModule', []);
app.config(function($provide) {
var base = angular.injector(['myAppBaseModule']);
$provide.constant('Foo', base.get('Foo'));
$provide.constant('serviceFoo', base.get('serviceFoo'));
});
app.controller('appCtrl', function($scope, Foo, serviceFoo) {
$scope.appHello = (new Foo("app")).hello();
$scope.serviceHello = serviceFoo.hello();
});
Using $injector to call service methods in config
I had a similar issue and resolved it by using the $injector service as shown above. I tried injecting the service directly but ended up with a circular dependency on $http. The service displays a modal with the error and I am using ui-bootstrap modal which also has a dependency on $https.
$httpProvider.interceptors.push(function($injector) {
return {
"responseError": function(response) {
console.log("Error Response status: " + response.status);
if (response.status === 0) {
var myService= $injector.get("myService");
myService.showError("An unexpected error occurred. Please refresh the page.")
}
}
}
A solution very easy to do it
Note : it's only for an asynchrone call, because service isn't initialized on config execution.
You can use run() method. Example :
Your service is called "MyService"
You want to use it for an asynchrone execution on a provider "MyProvider"
Your code :
(function () { //To isolate code TO NEVER HAVE A GLOBAL VARIABLE!
//Store your service into an internal variable
//It's an internal variable because you have wrapped this code with a (function () { --- })();
var theServiceToInject = null;
//Declare your application
var myApp = angular.module("MyApplication", []);
//Set configuration
myApp.config(['MyProvider', function (MyProvider) {
MyProvider.callMyMethod(function () {
theServiceToInject.methodOnService();
});
}]);
//When application is initialized inject your service
myApp.run(['MyService', function (MyService) {
theServiceToInject = MyService;
}]);
});
Well, I struggled a little with this one, but I actually did it.
I don't know if the answers are outdated because of some change in angular, but you can do it this way:
This is your service:
.factory('beerRetrievalService', function ($http, $q, $log) {
return {
getRandomBeer: function() {
var deferred = $q.defer();
var beer = {};
$http.post('beer-detail', {})
.then(function(response) {
beer.beerDetail = response.data;
},
function(err) {
$log.error('Error getting random beer', err);
deferred.reject({});
});
return deferred.promise;
}
};
});
And this is the config
.when('/beer-detail', {
templateUrl : '/beer-detail',
controller : 'productDetailController',
resolve: {
beer: function(beerRetrievalService) {
return beerRetrievalService.getRandomBeer();
}
}
})
Easiest way:
$injector = angular.element(document.body).injector()
Then use that to run invoke() or get()

Resources