5

During moving my code from RC4 to 2.1.2, I encountered a strange problem: all my constructor parameters get their value undefined.

I have tried to move providers around from component to app.module.ts to app.component.ts. None of them works.

What's new in 2.1.2 that could make the dependency injector inject "undefined" instead of creating/providing a service instance?

Notes

  1. To make things simpler I changed my code to the following
  2. There is no error message.
  3. If I don't add @Injectable() to AppComponent I would get Can't resovle all parameters for AppComponent (?,?,?)
  4. Please note that the root injector failed to create both the user service and Router instance to feed the AppComponent constructor.
  5. AuthService used to inject Http but I removed it along with other code so that there are less variables to the puzzle.
  6. Tried in Angular 2.2.0 it does not work either.

Any further input?

app.component.ts

import { Component,Injectable }       from '@angular/core'; 
import { Router  } from '@angular/router'; 
import { AuthService }  from '../login/auth.service';

@Component({
  selector: 'my-app',
  template: `
    <h1 class="title">Angular Router</h1>
    <nav>
    </nav>
    <router-outlet></router-outlet>
  `
})
@Injectable()
export class AppComponent {
  constructor(                            // debug here
              private auth: AuthService,  // auth = undefined
              private router: Router,     // router = undefined
              ) {
                console.log("AppComponent constructor");
              }  
}

app.module.ts

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

import { AppComponent }         from './app.component';
import { AuthService }  from '../login/auth.service';

@NgModule({
  imports: [
    BrowserModule,
    FormsModule,
    RouterModule.forRoot([
      { path: '', component: AppComponent },
    ])
  ],
  declarations: [ AppComponent ],
  exports: [RouterModule],
  providers:[AuthService ],
  bootstrap: [ AppComponent ]
})
export class AppModule {}

auth.service.ts

import {Injectable} from '@angular/core';

@Injectable()
export class AuthService {  // the debugger can get to this line but never hit constructor
  private _baseUrl: string;
  loggedIn: boolean = false;
  redirectUrl: string;

  constructor() {
    console.log("AuthService constuctor");
    this.loggedIn = !!sessionStorage.getItem('auth_token');
  }

}

main.ts

import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './appShell/app.module';
platformBrowserDynamic().bootstrapModule(AppModule);

systemjs.config.js

(function(global) {

  var ngVer = '@2.1.2'; // lock in the angular package version; do not let it float to current!
  var routerVer = '@3.1.2'; // lock router version

  //map tells the System loader where to look for things
  var  map = {
    'app':                        'app',

    // angular bundles
    '@angular/core': 'https://npmcdn.com/@angular/core' + ngVer,
    '@angular/common': 'https://npmcdn.com/@angular/common' + ngVer,
    '@angular/compiler': 'https://npmcdn.com/@angular/compiler' + ngVer,
    '@angular/platform-browser': 'https://npmcdn.com/@angular/platform-browser' + ngVer,
    '@angular/platform-browser-dynamic': 'https://npmcdn.com/@angular/platform-browser-dynamic' + ngVer,
    '@angular/http': 'https://npmcdn.com/@angular/http' + ngVer,
    '@angular/router': 'https://npmcdn.com/@angular/router' + routerVer,
    '@angular/forms': 'https://npmcdn.com/@angular/forms' + ngVer,
    '@angular/upgrade': 'https://npmcdn.com/@angular/upgrade' + ngVer,

    // Other libraries
    'rxjs':                       'https://npmcdn.com/[email protected]',
    'angular-in-memory-web-api':  'https://npmcdn.com/angular-in-memory-web-api', // get latest
    'ts':                         'https://npmcdn.com/[email protected]/lib/plugin.js',
    'typescript':                 'https://npmcdn.com/[email protected]/lib/typescript.js',

 };

  //packages tells the System loader how to load when no filename and/or no extension
  var packages = {
    'app':                        { main: 'main.ts',  defaultExtension: 'ts' },
    'rxjs':                       { defaultExtension: 'js' },
    'angular2-in-memory-web-api': { main: 'index.js', defaultExtension: 'js' },
  };    
  var config = {
    // DEMO ONLY! REAL CODE SHOULD NOT TRANSPILE IN THE BROWSER
    transpiler: 'ts',
    meta: {
      'typescript': {
        "exports": "ts"
      }
    },
    map: map,
    packages: packages
  };
  System.config(config);
})(this);

package.json

{
  "name": "TestApp",
  "version": "1.0.0",
  "scripts": {
    "start": "tsc && concurrently \"tsc -w\" \"lite-server\" ",
    "lite": "lite-server",
    "tsc": "tsc",
    "tsc:w": "tsc -w"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@angular/common": "~2.1.2",
    "@angular/compiler": "~2.1.2",
    "@angular/core": "~2.1.2",
    "@angular/forms": "~2.1.2",
    "@angular/http": "~2.1.2",
    "@angular/platform-browser": "~2.1.2",
    "@angular/platform-browser-dynamic": "~2.1.2",
    "@angular/router": "~3.1.2",
    "@angular/upgrade": "~2.1.2",

    "angular-in-memory-web-api": "~0.1.13",
    "core-js": "^2.4.1",
    "reflect-metadata": "^0.1.8",
    "rxjs": "5.0.0-beta.12",
    "systemjs": "0.19.40",
    "zone.js": "^0.6.26"
  },
  "devDependencies": {
    "@types/core-js": "^0.9.34",
    "@types/node": "^6.0.46",
    "concurrently": "^3.1.0",
    "lite-server": "^2.2.2",
    "typescript": "^2.0.3"
  },
  "repository": {}
}
6
  • You don't need @Injectable() when there is already @Directive(), @Component(), or @Pipe() Commented Nov 14, 2016 at 15:27
  • You should at least get an error message. Did you add FormsModule, and ReactiveFormsModule to imports of the @NgModule()? I don't think you need to add FormBuilder to providers. Adding FormsModule to imports should do. Commented Nov 14, 2016 at 15:28
  • Did you use @Injectable() in your service classes? Commented Nov 14, 2016 at 22:22
  • Are you sure the double .. are correct here import { AuthService } from '../login/auth.service';? Commented Nov 16, 2016 at 20:38
  • yes. '../login/auth.service' is correct. Commented Nov 16, 2016 at 20:44

3 Answers 3

2

In RC.5 @NgModule was introduced.
You need to declare additional services, modules etc. like this:

import {NgModule} from '@angular/core';
import {LoginComponent} from './login.component';
import {Router,RouterModule} from '@angular/router';
import {FormsModule, FormBuilder} from '@angular/forms';
import {AuthService} from './auth.service';
import {routing} from './app.routing.module';
import {MainComponent} from './main.component';

@NgModule({
  declarations: [LoginComponent], // specify your components here
  imports: [BrowserModule, FormsModule, RouterModule.forRoot([...]), routing],
  providers: [FormBuilder, AuthService, ...], // additional providers
  bootstrap: [MainComponent],
})
class AppModule {}

More info

Sign up to request clarification or add additional context in comments.

1 Comment

Hey, Günter Zöchbauer and Lenny, thanks for the input. I updated my post and added more info. I tried your suggestions but so far it didn't work yet. When you read my update you may be able to see what I did wrong?
0

Finally I found it. In systemjs.config.js add the following and it worked fine.

typescriptOptions: {
  emitDecoratorMetadata: true
},

Comments

0

I have a little suggestion. Try not to use the @Injector decorator on a component, rather define a service and use it there. It makes your code much more readable.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.