I want to automatically dependency inject an Angular built-in service into all services within an Angular module / app.
The service I want to inject is ... $exceptionHandler
I do not want $exceptionHandler to be global ... e.g. I do not want to do ...
window.$exceptionHandler = $exceptionHandler
But I also do not want to dependency inject $exceptionHandler into every service manually using ...
angular.module('myApp').factory('myService', ['$exceptionHandler', function ($exceptionHandler) {
Is it possible to automatically inject an Angular built-in service into all services within an Angular module / app ?
Many thanks
It can be made more convenient through nested modules. In the root (or global) module inject $exceptionHandler and all the other modules you create or want to use. All sub modules of the root module will have $exceptionHandler injected without further ado. You still have to name the $exceptionHandler in your controller and factory function definitions, though, so it is not possible to completely get rid of injection artefacts.
Example:
app.js
angular.module('app', ['ionic', '$exceptionHandler', 'ngCordova','app.home',
'app.impressum'])
.run(function ($ionicPlatform, $state) {
..
})
.config(function ($stateProvider, $urlRouterProvider, $provide, $exceptionHandler, $ionicConfigProvider, $compileProvider) {
$stateProvider
.state('app', {
...
})
}
);
Now the app.home-Module:
home.js
angular.module('app.home', ['app.home.controller', 'app.home.factory']);
home/controller.js
angular.module('app.home.controller', [])
.controller('homeController', function ($scope, $exceptionHandler) {
...
});
app.home.factory and the three modules for app.impressum are quite similar, so I leave that to you.
As you can see you still have to put $exceptionHandler into the function parameters of your controller, but no injection is required on the module itself, because it inherits all injections from it's parent modules app.home and app.
By using a hierarchy of modules in an AngularJS app injections can be made where due... more globally for the whole app, for module groups or only on single modules. Plus we get a very clean structure for the App's sections.
Related
I have a service that needs to be called in the app's config module but it errors when I try to inject it. Any ideas? FYI - this service works perfectly fine in controllers when injected and executed.
app.config(['$routeProvider', 'myService', function($routeProvider, myService) {
var controller = myService.getSomeValue() ? 'FirstController', 'SecondController';
$routeProvider
.when('/', {
'templateUrl': '/myTemplate.html'
'controller': controller
})
});
Failed to instantiate module app due to:
Error: [$injector:unpr] http://errors.angularjs.org/1.5.7/$injector/unpr?p0=myService
The AngularJS framework operates in two phases, the config phase and the run phase. Only provider objects can be injected in the config phase. Services can only be injected during the run phase.
From the Docs:
module.config(configFn);
Use this method to configure services by injecting their providers, e.g. for adding routes to the $routeProvider.
Note that you can only inject providers and constants into this function.
For more about how to configure services, see Provider Recipe.
For more information, see
AngularJS module type API Reference - config
AngularJS Developer Guide - Providers - Summary
I have this global set up for my angular App module:
var App = angular.module('App', [], function ($interpolateProvider) {
//$interpolateProvider.startSymbol('<%');
//$interpolateProvider.endSymbol('%>');
});
I include it in all pages with angular stuff.
I then have a controller loaded on a page that requires a service called 'angularFileUpload':
App.controller('FileUploadController', ['$scope', 'FileUploader', function ($scope, FileUploader) {
If i place that service inside the module array, it works fine. Is there a way of just attaching it to this controller instead... this means i do not have to load the script files for every page using this module regardless of if the controllers require the angularfileUpload service or not.
Edit: regarding the last comment
If i declare:
var App = angular.module('App');
How do i then add that service to the module?
I want to inject Restangular in my app to communicate with via REST.
So, here I am know with an error:
Error: [$injector:unpr] Unknown provider: RestangularProvider <- Restangular <- Api
Api is my own module here. What I'm doing:
Creating a main module called Dashboard
Creating a submodule called API
Now I want to use Restangular, but couldn't figure out how Angular is managing the dependencies...
Here is my sub-module where I inject Restangular:
angular.module( 'dashboard.api', ['restangular']).factory('Api', ['$http', 'Config', 'Restangular', function($http, Config, Restangular) {
My main module, Dashboard, doesn't need to inject Restangular, right?
angular.module( 'dashboard', [ 'dashboard.api'])
How is the injection-depency working within submodules? How can I
integrate Restangular in my app?
EDIT: Source file is included:
Okay I found the problem and the solution.
You have to differ between restangular(the module) and Restangular the service.
First, you have to include the main module of restangular into your app:
For me, it was this (polygon is a submodule of my app:
angular.module('polygons', ['restangular']);
Then, I wanted to inject restangular into a factory of that submodule:
angular.module('polygons').factory('polygonService', ['Restangular', polygonService]);
function polygonService(Restangular) {
// ...
});
This works for me. Hope this helps.
When trying to implement the session part in the tutorial of John Papa Pluralsight Video.
I got the following error:
Uncaught TypeError: Object # has no method 'extendQ'
(function () {
'use strict';
var app = angular.module('app', [
// Angular modules
'ngAnimate', // animations
'ngRoute', // routing
'ngSanitize', // sanitizes html bindings (ex: sidebar.js)
// Custom modules
'common', // common functions, logger, spinner
'common.bootstrap', // bootstrap dialog wrapper functions
// 3rd Party Modules
'ui.bootstrap', // ui-bootstrap (ex: carousel, pagination, dialog)
//'breeze.angular.q'
]);
// Handle routing errors and success events
app.run(['$route', '$rootScope', '$q', function ($route, $rootScope, $q) {
// Include $route to kick start the router.
breeze.core.extendQ($rootScope, $q);
//use$q($rootScope,$q);
}]);
})();
It's important to know that the version of breeze that I'm working on is newer than the used on the original video.
I search for some answers on the breeze website and I've found this:
The to$q has been deprecated. It is superseded by the Breeze Angular Service.
But I didn't make it work on the tutorial example. How to change the deprecated implementation with the new one?
UPDATE:
this link helped solve the problem:
http://www.breezejs.com/documentation/breeze-angular-service
The breeze library was updated and the answer is on this link: http://www.breezejs.com/documentation/breeze-angular-service
Specifically this code from the bottom of the post:
Migration is pretty painless.
Remove the breeze.angular.q.js script from your project.
Uninstall-Package Breeze.Angular.Q if you used NuGet.
Install breeze.angular.js as explained above.
Update your index.html, changing breeze.angular.q.js to breeze.angular.js.
Update your app module to depend on "breeze.angular".
Find the one place in your code where you call "use$q" and replace it with the "breeze" dependency.
For example, you might go from this:
var app = angular.module('app', [
// ... other dependencies ...
'breeze.angular.q' // tells breeze to use $q instead of Q.js
]);
app.run(['$q','use$q', function ($q, use$q) {
use$q($q);
}]);
to this:
var app = angular.module('app', [
// ... other dependencies ...
'breeze.angular'
]);
app.run(['breeze', function () { }]);
You should also track down and eliminate code that configures Breeze to use the "backingStore" model library adapter and $http. For example, you could go from this:
function configBreeze($q, $http, use$q) {
// use $q for promises
use$q($q);
// use the current module's $http for ajax calls
var ajax = breeze.config.initializeAdapterInstance('ajax', 'angular');
ajax.setHttp($http);
// the native Breeze 'backingStore' works for Angular
breeze.config.initializeAdapterInstance('modelLibrary', 'backingStore', true);
breeze.NamingConvention.camelCase.setAsDefault();
}
to this:
function configBreeze() {
breeze.NamingConvention.camelCase.setAsDefault();
While taking the same course by John Papa I also hit breeze.core.extendQ not available on step 4.10.
This is what I did to solve the issue:
1 - In app.js pass breeze dependency directly:
// Handle routing errors and success events
// Trigger breeze configuration
app.run(['$route', 'breeze', function($route, breeze)
{
// Include $route to kick start the router.
}]);
2 - In datacontext.js do:
return EntityQuery.from('Sessions')
.select('id, title, code, speakerId, trackId, timeSlotId, roomId, level, tags')
.orderBy(orderBy)
.toType('Session')
.using(manager).execute()
.then(querySucceeded, _queryFailed);
You can also get rid of breeze.to$q.shim.js from index.html and delete the file from the \Scripts folder in the project since it's not needed anymore.
Here's the updated source code of the same project I'm doing now [ including the fixes ].
Assuming I have a service MyService that has a property "data" that contains contents retrieved from 2 or 3 $http requests and stores it into "data". This "data" needs to be accessible or passed to a directive to process, (like a modal).
The service "MyService" contains an attribute "data" necessary for myDirective to process on first load.
// var app = angular.module...
app.service('MyService',...)
I have a separate directive "myDirective":
var myDirective = angular.module('myDirective', []);
myDirective.directive('control', ['Params', function(Params) {...
I tried to inject "MyService" by doing the following:
var myDirective = angular.module('myDirective', ['MyService']);
myDirective.directive('control', ['Params', function(Params) {...
Though it fails to instantiate saying:
error: [$injector:nomod] Module 'MyService' is not available! You either misspelled the module name or forgot to load it.
If registering a module ensure that you specify the dependencies as the second argument.
How do I properly instantiate my myDirective from myService? Is this the right approach or should I be using some controller/factory/provider?
You are treating myService as a module which it is not, it is a component of a module. You only inject modules into other modules. Once all dependent modules are injected into main module, components of all modules are directly available to other components, regardless of which module they are initially registered to.
To inject into a directive you do it the same way you are injecting Params into directive. I suspect you are needlessly creating a new module just to create a directive.
Try this way:
app.service('MyService',...);
app.directive('control', ['Params','MySerrvice', function(Params,MyService) {...
Now within the directive you have access to objects in service using MyService.propertyName
What you are trying is adding MyService service as a module to your MyDirective module which won't work.
The easy way would be to just add the directive to your app module and inject your service:
app.directive('control', ['Params', 'MyService', function(Params, MyService) {
//...
}]);
If you create extra modules for your directives and and maybe also for your services you will have to add these modules to your app module like for example (usually in app.js):
var directivesModule = angular.module('app.directives', []);
var servicesModule = angular.module('app.services', []);
var app = angular.module('app', ['app.directives', 'app.services']);
And then add your services and directives to the respective modules:
servicesModule.service('MyService',...);
directivesModule.directive('control', ['Params','MyService', function(Params, MyService) {
//...
}]);
Create one file per service/directive or a file for all services and one for all directives. Depends on the size of your app.