I'm creating a login system for Angular application and got stuck on unknown provider error. I checked everything for 5 times and I don't see what's wrong.
I'm using Webpack as a build system.
The error text is as follows:
angular.js:68 Uncaught Error: [$injector:modulerr] Failed to instantiate module Universe due to:
Error: [$injector:modulerr] Failed to instantiate module layout due to:
Error: [$injector:unpr] Unknown provider: Self
Under suspition are 4 javascript files, constituting 3 modules:
app.js
- containsUniverse
modulelayout.module.js
- containslayout
moduleauth.module.js
- containsauth
moduleself.service.js
- containsSelfResource
factory forSelf
service inauth
Resource factory Self
, representing information about logged-in user, is causing the error.
app.js
'use strict';
require("expose?$!expose?jQuery!jquery");
require("metisMenu/dist/metisMenu");
require("iCheck/icheck");
require("expose?_!lodash"); // was underscore
var angular = require("angular");
require("angular-animate");
require("angular-messages");
require("angular-resource");
require("angular-sanitize");
require("angular-cookies");
require("angular-ui-router");
require("bootstrap/dist/css/bootstrap.css");
require("font-awesome/css/font-awesome.css");
require("angular-bootstrap");
require("../assets/styles/style.scss");
require("../assets/fonts/pe-icon-7-stroke/css/pe-icon-7-stroke.css");
require("../assets/fonts/pe-icon-7-stroke/css/helper.css");
// Import all html files to put them in $templateCache
// If you need to use lazy loading, you will probably need
// to remove these two lines and explicitly require htmls
const templates = require.context(__dirname, true, /\.html$/);
templates.keys().forEach(templates);
var LayoutModule = require("layout/layout.module");
var HomeModule = require("home/home.module");
var AccountModule = require("account/account.module");
var WorkflowModule = require("workflow/workflow/workflow.module");
var TaskModule = require("workflow/task/task.module");
var ToolModule = require("workflow/tool/tool.module");
var NavigationModule = require("../components/navigation/navigation.module");
var PanelModule = require("../components/panel/panel.module");
var UniverseDirectives = require("../components/directives");
var AuthModule = require("../components/auth/auth.module");
angular.module("Universe", [
"ngAnimate",
"ngMessages",
"ngResource",
"ngSanitize",
"ngCookies",
"ui.router",
"ui.bootstrap",
LayoutModule.name,
HomeModule.name,
AccountModule.name,
WorkflowModule.name,
TaskModule.name,
ToolModule.name,
NavigationModule.name,
PanelModule.name,
UniverseDirectives.name,
AuthModule.name
])
.config(function($urlRouterProvider, $locationProvider, $stateProvider) {
// $urlRouterProvider.otherwise('/');
// $locationProvider.html5Mode(true);
$stateProvider
.state('test', {
url: "/test",
template: "This is a test"
});
})
.run(function($rootScope, Auth) {
$rootScope.Auth = Auth;
});
layout.js
import angular from "angular";
// @ngInject
function routes($stateProvider, Self) {
$stateProvider.state("layout", {
url: "",
abstract: true,
templateUrl: "/app/layout/layout.html",
resolve: {
self: function() {
var self = Self({});
return self;
}
}
});
}
//export default
module.exports = angular.module("layout", ["auth"]).config(routes);
auth.module.js
'use strict';
var AuthService = require("./auth.service");
var UserResource = require("./user.service");
var SelfResource = require("./self.service");
var AuthInterceptor = require("./interceptor.service");
var UtilModule = require("../util/util.module");
module.exports = angular.module('auth', [
'ui.router',
UtilModule.name
])
.factory('Auth', AuthService)
.factory('User', UserResource)
.factory('Self', SelfResource)
.factory('AuthInterceptor', AuthInterceptor)
.config(function($httpProvider) {
$httpProvider.interceptors.push('AuthInterceptor');
})
.run(function($rootScope, $state, Auth) {
// This is router decorator, it redirects users, lacking priviledges, to login page
// Redirect to login if route requires auth and the user is not logged in, or doesn't have required role
$rootScope.$on('$stateChangeStart', function(event, next) {
if (!next.authenticate) {
return;
}
if (typeof next.authenticate === 'string') {
Auth.hasRole(next.authenticate, _.noop).then(has => {
if(has) {
return;
}
event.preventDefault();
return Auth.isLoggedIn(_.noop).then(is => {
$state.go(is ? 'main' : 'login');
});
});
}
else {
Auth.isLoggedIn(_.noop).then(is => {
if(is) {
return;
}
event.preventDefault();
$state.go('main');
});
}
});
});
self.service.js
'use strict';
// @ngInject
function SelfResource($resource) {
return $resource('/api/self/',
{},
{
get: {
method: 'GET'
}
},
{
stripTrailingSlashed: false
}
);
}
module.exports = SelfResource;
So, everything should work: I imported SelfResource
in auth.module.js
and declared it as a factory. I also declared auth
module, defined in auth.module.js
, as a dependency for layout module.
Webpack compiles without errors, all the modules are present in the output bundle. Why error?
UPDATE:
I added the following lines to the beginning of layout.module.js
:
var authModule = require("../../components/auth/auth.module");
console.log(authModule);
that gave me the contents of auth
module:
Object {_invokeQueue: Array[4], _configBlocks: Array[1], _runBlocks: Array[1], requires: Array[2], name: "auth"}
Its _invokeQueue
contains the Self
factory. So, I guess it's a strange problem on the receiving side.