angular js injector module error - javascript

i am new to angular js i am trying to inject factory in a config ,but it shows module not found
factory code
var app=angular.module('app',['ui.router','angular-jwt','ngResource','angularValidator','satellizer']);
app.factory('AUTH_SERVICE', function ($auth,$state,$q) {
var auth={};
auth.isloggedin=function() {
var defer = $q.defer();
if($auth.isAuthenticated()){
defer.resolve();
}
else
{
$state.go('login');
defer.reject();
}
return defer.promise;
}
return auth;
});
config code is
app.config(['AUTH_SERVICE','$authProvider','$stateProvider', '$urlRouterProvider',function(AUTH_SERVICE,$stateProvider, $urlRouterProvider,$authProvider) {
$urlRouterProvider.otherwise('/');
$stateProvider
.state('home',{
url:'/',
templateUrl:'pages/home.html'
})
.state('login',{
url:'/login',
templateUrl:'pages/login.html',
controller:'loginCtrl'
})
.state('register',{
url:'/register',
templateUrl:'pages/register.html',
controller:'registerCtrl'
})
.state('dashboard',{
url:'/Dashboard',
templateUrl:'pages/dashboard.html',
controller:'dashctrl',
resolve:{
skiplogin: _skiplogin
}
})
function _skiplogin(AUTH_SERVICE){
return AUTH_SERVICEAUTH_SERVICE.isloggedin();
}
}]);
but it shows error
angular.js:38Uncaught Error: [$injector:modulerr]
http://errors.angularjs.org/1.5.8/$injector/modulerr?p0=app&p1=Error%3A%20%…ocalhost%2Faccoex%2Fbower_components%2Fangular%2Fangular.min.js%3A39%3A319)

You can't inject factory object in the app.config because it can't be sure they have been loaded correctly..
In the app.config you can only inject Consts and Providers.
From the documentation
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.
Run blocks - get executed after the injector is created and are used
to kickstart the application. Only instances and constants can be
injected into run blocks. This is to prevent further system
configuration during application run time.
Take a look to provider here where you can configure a service in your app.config.

you can't inject factory in config as it loads after config
angularjs application loads as follows:
Run
Config
Instantiate factory or service
Controller

Related

AngularJS: directive/dependency injection

To add dependency to Angular, this is what docs tells to do :
Source
//inject directives and services.
var app = angular.module('fileUpload', ['ngFileUpload']);
app.controller('MyCtrl', ['$scope', 'Upload', function ($scope, Upload) {...
But can we inject directive directly into controller like this:
var app = angular.module('fileUpload', []);
app.controller('MyCtrl', ['ngFileUpload','$scope', 'Upload', function (ngFileUpload,$scope, Upload) {...
If not, what is the reason for not providing this capability to controller?
Is there a way to inject dependency when a particular controller loads?
No modules are the essentially the base or a "toolbox" if you will. You need to inject one module into another so that the it can have access to its "tools" (filters/directives/services etc). The reason is that the module is responsible for dependency loading and order of operations. This is so that when you request a "tool" from a module into a controller you can be sure it is there (or an error will be thrown).
Modules can list other modules as their dependencies. Depending on a module implies that the required module needs to be loaded before the requiring module is loaded. In other words the configuration blocks of the required modules execute before the configuration blocks of the requiring module. The same is true for the run blocks. Each module can only be loaded once, even if multiple other modules require it.
When you inject one module into another you are saying "Module A requires things from Module B". Now when you when you require a specific tool that is when you inject it into the controller so that you have access to that specific tool.
So consider:
var app = angular.module('myApp', ['ngFileUpload']);
app.controller('MyCtrl', ['$scope', 'Upload', function ($scope, Upload) {
.....
Upload.upload(uploadData).then(function (resp) {
//success
}, null, function (evt) {
//upload progress
});
.....
}]);
So because you inject ngFileUpload your controller in the myApp module can now inject the Upload service from the ngFileUpload module and the controller does not need to worry if the service is present (if it is not you will get an injection error from angular).

AngularJS: how to use $http in config phase

I am building a single page application using angular. We use Continuous Integration with several Dev and QA environments. This means that every time I deploy the app in a different environment I need to update some config parameters such as SPA baseUrl, rest api url or url for my oauth server.
To achieve this, our CI engine generates a config.json file with the correct parameters for each environment when we are about to deploy there. To get this I have created a really simple service:
(function () {
'use strict';
angular
.module('app.core')
.factory('config', config);
config.$inject = ['$http'];
function config($http) {
return {
load: load
};
//////////
function load() {
return $http.get('assets/config/config.json');
}
}
}());
Most of my services are configured through providers during the config phase. And here is where the problem comes up. As you know, services cannot be injected during this phase but I would like to use config service to set up my providers with the correct URLs and parameters.
Is there a proper way to do this?
The only thing I can consider so far is having these config parameters embed in my module creation file so they are there ready to use. It seems quite ugly since I don´t want any external process to my app modifying my source code.
If these are asynchronous services that rely on config.json, it is perfectly ok to change the way they are configured and fit your config into async workflow, e.g.
app.factory('config', function ($http) {
return $http.get('config.json', { cache: true })
.then(function (response) {
return response.data;
});
});
app.factory('asyncService', function ($http, config) {
return config.then(function (config) {
return $http...
}).then(...);
});
Otherwise the best option is to build json config to a service with Gulp/Grunt/whatever.
Think of
angular.module('config', []).constant('config', <%= configJson %>);
as of a compiled template rather than 'external process to my app modifying my source code'.
What I am doing at the moment (but I am open for a better solution) is to have a separate config file with the json object that contains all the config info.
Example of the file content:
var appConfigInfo = {
DEV: true,
API_PATH: 'your_custom_url'
// etc.
};
Then I add it as a constant in my app. Example:
angular
.module('app', [])
.constant('APP_CONFIG', appConfigInfo);
Now you can access all your configuration values via the constant. Don't forget to inject it in your controllers, etc.
I hope it helps.

AngularJS and Webpack Integration

I am looking for some help with using webpack for a large AngularJS application. We are using folder structure based on feature (each feature/page has a module and they have controllers, directives). I have successfully configured webpack to get it working with Grunt, which produces one single bundle. I want to create chunks as its going to be a large app, we would like to load modules (page/feature) artifacts asynchronously.
I am going through some of the webpack example to use 'code splitting' using require([deps],fn ) syntax. However I couldn't get the chunks lazy-loaded. First of all, I don't know where exactly, I would need to import these chunks before AngularJS would route the user to next page. I am struggling to find a clear separation of responsibility.
Did someone point me to an example AngularJS application where webpack is used to load controllers/directives/filters asynchronously after each route?
Few of the links I am following:
Should I use Browserify or Webpack for lazy loading of dependancies in angular 1.x
https://github.com/petehunt/webpack-howto#9-async-loading
http://dontkry.com/posts/code/single-page-modules-with-webpack.html
Sagar Ganatra wrote a helpful blog post about code splitting.
Suprisingly code splitting isn't really supported by angular's module system. However, there is a way to achieve code splitting by saving a reference to angular's special providers during the config-phase.
[...] when Angular initializes or bootstraps the application, functions - controller, service etc,. are available on the module instance. Here, we are lazy loading the components and the functions are not available at a later point; therefore we must use the various provider functions and register these components. The providers are available only in the config method and hence we will have to store a reference of these providers in the config function when the application is initialized.
window.app.config([
'$routeProvider',
'$controllerProvider',
'$compileProvider',
'$filterProvider',
'$provide',
function ($routeProvider, $controllerProvider, $compileProvider, $filterProvider, $provide) {
$routeProvider.when('/login', {
templateUrl: 'components/login/partials/login.html',
resolve: {
load: ['$q', '$rootScope', function ($q, $rootScope) {
var deferred = $q.defer();
// lazy load controllers, etc.
require ([
'components/login/controllers/loginController',
'components/login/services/loginService'
], function () {
$rootScope.$apply(function () {
deferred.resolve();
});
});
return deferred.promise;
}]
}
});
//store a reference to various provider functions
window.app.components = {
controller: $controllerProvider.register,
service: $provide.service
};
}
]);
Now inside your loginController for instance you write
app.components.controller('loginController');
to define your new controller lazily.
If you want to lazy-load your templates too I recommend to use the ui-router. There you can specify a templateProvider which is basically a function to load templates async
This is a quote from
https://github.com/webpack/webpack/issues/150
webpack is a module bundler not a javascript loader. It package files from local disk and don't load files from the web (except its own chunks).
Use a javascript loader, i. e. script.js
var $script = require("scriptjs");
$script("//ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular.min.js", function() {
// ...
});

AngularJS, jasmine unit test throws 'Unknown provider' error

I'm trying to write a simple unit test for a controller in my app, but Jasmine is throwing an 'Unknown provider' error. It's choking on a provider that I wrote to help with retrieving template urls. The provider is injected into a config function so I can use it in routes.js.
The specific error I am getting is: Error: Unknown provider: assetPathProvider
Here is my Karma config:
files: [
'vendor/assets/javascripts/jquery.js',
'vendor/assets/javascripts/angular.js',
'spec/javascripts/lib/angular/angular-mocks.js',
'vendor/assets/javascripts/angular-*.js',
'vendor/assets/javascripts/*.js',
'app/assets/javascripts/initialize.js',
'app/assets/javascripts/**/*.js',
'spec/javascripts/unit/**/*.js'
],
I initialize my app like so:
Viewfinder = angular.module('viewfinder', [
'ui.bootstrap',
'scroll',
'ngCookies',
'ngResource',
'chart',
'http-auth-interceptor',
'facebook-connect',
'twitter-connect',
'Alerts',
'smartTable.table',
'ngClipboard',
'angularFileUpload'
])
Here is the top of routes.js
Viewfinder.config(['$routeProvider', '$locationProvider', 'assetPathProvider', function($routeProvider, $locationProvider, assetPathProvider) {
The provider is used in retrieving the correct template location in routes.js
...
templateUrl: assetPathProvider.get('welcome/signed_in.html'),
....
Here is the provider itself:
Viewfinder.provider('assetPath', [function() {
this.get = function(path) {
if(angular.isDefined(gon.config.manifest)) {
return '/assets/' + gon.config.manifest[path]
} else {
return '/assets/' + path
}
}
this.$get = function() {
return {
get: this.get
}
}
}]);
I've dumbed down my spec to be as simple as possible, but I can't get past the Unknown provider error.
Here is the spec:
describe('OneSheetPackagesViewController', function() {
var $rootScope, $scope, $controller, message
beforeEach(function() {
module('viewfinder', function(assetPathProvider) {})
})
beforeEach(inject(function(_$rootScope_) {
message = 'hello'
}))
it("should successfully submit a comment", function() {
console.log(message)
expect(message).toBeDefined()
})
})
Viewfinder.config(['$routeProvider', '$locationProvider', 'assetPathProvider', function($routeProvider, $locationProvider, assetPathProvider)
will be executed before
Viewfinder.provider('assetPath'
This when config is being executed assetPathProvider is not available.
http://docs.angularjs.org/guide/module
Module Loading & Dependencies 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. Run blocks - get
executed after the injector is created and are used to kickstart the
application. Only instances and constants can be injected into run
blocks. This is to prevent further system configuration during
application run time.
Try writing the provider in another angular module and inject it as dependency to viewfinder. also remember to ensure that the file defining assetPath appears before the viewfinder in karma.conf

How do I get an Angularjs module and invoke .value on it?

I'm trying to use a vertxbus module. It's configuration is set using .value.
How do I update these configuration values from my 'appModule'?
To my understanding
angular.module('knalli.angular-vertxbus')
should return a reference to the module and .value should change the injected value.
I've created a jsFiddle and here is the js used:
'use strict';
var testmodule = angular.module('TestModule', []).value('key', 'module').value('key', 'module2');
testmodule.factory('MyService', ['key', function (key) {
return key;
}]);
var module = angular.module('myApp', ['TestModule'])
.run(function () {
testmodule.value('key', 'run1');
angular.module('TestModule').value('key', 'run2');
}).controller('MyCtrl', ['$scope', 'MyService', 'key', function ($scope, MyService, key) {
$scope.value = MyService;
$scope.key = key;
}]);
I would expect a result of run2 or at least run1 but module2 is returned. Why?
The actual idea behind .value, .constant or more generally .config is the possibility to change how the modules' components should constructed themselves.
In that case, the angular-translate's vertxBus component will invoke implicitly a SockJS instance which connects implicitly to a server. That means the configuration settings must be known before the application will be running. Because of this, there are two phases (see answer by Ilan Frumer): config and run.
However, because .value and .config are too static and could collide with other components, the angular module angular-vertxbus has an own provider for all the settings (since version 0.5: https://github.com/knalli/angular-vertxbus/releases/tag/v0.5.0).
Starting with 0.5, this could be look like this:
var module = angular.module('app', ['knalli.vertx-eventbus']);
module.config(function(vertxEventBus) {
vertxEventBus.useDebug(true).useUrlPath('/eventbus');
});
Just like the others, the provider is only available in the config-phase.
Disclaimer: I'm the author of angular-vertxbus
$provide shorthands
Under the hood, constant & value & service & factory & provider are all shorthands for the $provide service which is available only during the configuration phase.
From angular.js documentation:
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.
Run blocks - get executed after the injector is created and are used to kickstart the application. Only instances and constants can be injected into run blocks. This is to prevent further system configuration during application run time.
your case:
You cannot register providers (in your case value) inside run blocks because they are only available during the configuration phase.
Read more about modules and $provide

Categories

Resources