mbryja
mbryja

Reputation: 61

Angular 2 Can't Resolve Router Dependency

When I'm trying to inject Router into my Authentication Guard I get the following error:

Can't resolve all parameters for AuthenticationGuardService: (?)

Unfortunately, I cannot use node server as this is one of the project requirements (team decision). Instead I'm compiling ts files to ES5 and serving it from php app which runs on nginx server.

I may be missing some dependency or it is another case of circular dependencies. I'm not sure how to resolve it.

authentication-guard.service.js

import { Injectable } from '@angular/core';;
import {Router, CanActivate } from '@angular/router';

@Injectable()
export class AuthenticationGuardService implements CanActivate {

    constructor(
        private router: Router,
    ) {}

    canActivate() {
        this.router.navigate(['login']);
        return false;
    }

}

app.module.ts

import { NgModule }                         from '@angular/core';
import { BrowserModule }                    from '@angular/platform-browser';
import { FormsModule }                      from '@angular/forms';
import { HttpModule }                       from '@angular/http';

import { AppComponent}                from './app.component';
import { AppRoutingModule}            from './app-routing.module';
import { AuthenticationComponent }    from './authentication/authentication.component';
import { AuthenticationGuardService } from './authentication/guards/authentication-guard.service';


@NgModule({
    imports: [
        BrowserModule,
        FormsModule,
        AppRoutingModule,
        HttpModule
    ],
    declarations: [
        AppComponent,
        AuthenticationComponent,
    ],
    providers: [
        AuthenticationGuardService,
    ],
    bootstrap: [ AppComponent ]
})
export class AppModule{}

app-routing.module.ts

import { NgModule }               from '@angular/core';
import { RouterModule, Routes }   from '@angular/router';
import { AuthenticationComponent} from './authentication/authentication.component'
import { DashboardComponent}      from './dashboard/dashboard.component'
import { AuthenticationGuardService }    from './authentication/guards/authentication-guard.service';

const routes: Routes = [
    { path: '', redirectTo: '/dashboard', pathMatch: 'full' },
    { path: 'login', component: AuthenticationComponent },
    { path: 'dashboard', component: DashboardComponent, canActivate: [AuthenticationGuardService]}
];

@NgModule({
    imports: [ RouterModule.forRoot(routes) ],
    exports: [ RouterModule ]
})
export class AppRoutingModule {}

package.json

{
  "name": "admin-app",
  "version": "1.0.0",
  "description": "admin application",
  "main": "index.js",
  "devDependencies": {
    "@angular/common": "~2.3.0",
    "@angular/compiler": "~2.3.0",
    "@angular/core": "~2.3.0",
    "@angular/forms": "~2.3.0",
    "@angular/http": "~2.3.0",
    "@angular/platform-browser": "~2.3.0",
    "@angular/platform-browser-dynamic": "~2.3.0",
    "@angular/router": "~3.3.0",
    "@types/core-js": "^0.9.35",
    "@types/node": "^6.0.52 ",
    "core-js": "^2.4.1",
    "grunt": "^0.4.5",
    "grunt-contrib-concat": "^1.0.1",
    "grunt-contrib-copy": "^1.0.0",
    "grunt-contrib-cssmin": "latest",
    "grunt-contrib-jshint": "~0.10.0",
    "grunt-contrib-less": "latest",
    "grunt-contrib-nodeunit": "~0.4.1",
    "grunt-contrib-uglify": "~0.5.0",
    "grunt-contrib-watch": "latest",
    "reflect-metadata": "^0.1.8",
    "rxjs": "5.0.0-rc.4",
    "systemjs": "0.19.40",
    "zone.js": "^0.7.2"
  },
  "author": "CC",
  "dependencies": {
    "grunt-ts": "^6.0.0-beta.3",
    "typescript": "^2.1.4"
  }
}

systemjs.config.js

 * Adjust as necessary for your application needs.
 */
(function (global) {
  System.config({
    paths: {
      // paths serve as alias
      'npm:': '/js/libraries/node_modules/'
    },
    // map tells the System loader where to look for things
    map: {
      // our app is within the app folder
      app: 'js/src',

      // angular bundles
      '@angular/core': 'npm:@angular/core/bundles/core.umd.js',
      '@angular/common': 'npm:@angular/common/bundles/common.umd.js',
      '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
      '@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
      '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
      '@angular/http': 'npm:@angular/http/bundles/http.umd.js',
      '@angular/router': 'npm:@angular/router/bundles/router.umd.js',
      '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',

      // other libraries
      'rxjs':                      'npm:rxjs',
      'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js'
    },
    // packages tells the System loader how to load when no filename and/or no extension
    packages: {
      app: {
        main: './main.js',
        defaultExtension: 'js'
      },
      rxjs: {
        defaultExtension: 'js'
      }
    }
  });
})(this);

Upvotes: 1

Views: 2817

Answers (2)

mbryja
mbryja

Reputation: 61

I think I've figured it out. I had incorrect compiler settings.

Before

        ts: {
            options: {
                target: "es5",
                module: "umd",
                declaration: false,
                noImplicitAny: false,
                removeComments: true,
                emitDecoratorMetadata: false,
                experimentalDecorators: true,
                sourceMap: false,
                moduleResolution: "node",
                suppressImplicitAnyIndexErrors: false
            },
            build : {
                src: ["app/**/*.ts"],
                dest: '../../webroot/js/src/'
            }
        },

Working Config

        ts: {
            options: {
                target: "es5",
                module: "umd",
                declaration: false,
                noImplicitAny: true,
                removeComments: true,
                emitDecoratorMetadata: true,
                experimentalDecorators: true,
                sourceMap: false,
                moduleResolution: "node",
                suppressImplicitAnyIndexErrors: true
            },
            build : {
                src: ["app/**/*.ts"],
                dest: '../../webroot/js/src/'
            }
        },

The problem was caused by emitDecoratorMetadata option which was set to false.


Update to my answer

The above answer will work for ng2 by try to use angular CLI build if possible. With every new release you may have to refactor above config. Also, you will need to specify build config for every lazy loaded module you create while ng-cli does it for you.

Upvotes: 1

Harald Wiesinger
Harald Wiesinger

Reputation: 681

in your app. module.ts this should be correct: import { AppRoutingModule} from './app.routing.module';

you have an - there

Upvotes: 0

Related Questions