1

All:

Im pretty new to Angular2, when I try to build a simple counter service like:

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

@Injectable()
export class Counter {
    count = 0;
    constructor(start = 0){
        this.count = start;
        // this.reset();
    }
    reset(start=0){
        this.count = start;
    }
    inc(){
        this.count++;
    }
    dec(){
        this.count--;
    }
    show(){
        return this.count;
    }
}

What I tried to do in constructor is set a default init parameter start to default the count to 0, but I get the error like:

(SystemJS) Can't resolve all parameters for Counter: (?).

My question is:

Is this because Angular2 will consider everything in constructor param list as dependency injection, no other type of param allowed set there or there is other reason for this error? And I have to use that reset() to achieve same purpose?

Is this correct?

Thanks

Kuan
  • 11,149
  • 23
  • 93
  • 201

1 Answers1

2

"Is this because Angular2 will consider everything in constructor param list as dependency injection"

Yes.

What you can do though to make this work, is to use @Optional. But this would be pointless, alone. When you would you ever provide the value anyway? So it would always be 0. Pointless.

If you want to provide arbitrary values for injection, you can use @Inject and configure the value using a token. For example

import { OpaqueToken, NgModule } from '@angular/core';

export const START = new OpaqueToken("some.token");

@NgModule({
  providers: [
    { provide: START, useValue: 100 }
  ]
})
export class AppModule {}

Now you can inject it and make it optional

import { Inject, Optional } from '@angular/core';
import { START } from './app.module';

constructor(@Optional @Inject(START) start = 0) {}
Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720
  • Thanks, so if I need a value, I need to define it as a value dependency. – Kuan Dec 18 '16 at 04:38
  • Yeah, but also consider whether or not you really need to get the value from the outside. If not, then there's no need to even have it as a constructor parameter. Or maybe this is even something that can just be added to a "constants" file, and just import the constants where you need it (instead of trying to inject) – Paul Samsotha Dec 18 '16 at 04:40
  • Get it. BTW, could you give a little detail about why Object literal notation should be used like `{ provide: START, useValue: 100 }` since START already has a value, why I still need to give a value to useValue, and if I use something similar like `{ provide: START, useClass: START }`( let us say START is a class now) since START is the class name, why we still need to specify START in provide? – Kuan Dec 18 '16 at 05:11
  • `START` is only the token (it is not a value). The token is how Angular knows what to inject for `@Inject`. It is not the value. `100` is the value. If we want to do something like `{ provide: SomeService, useValue: new SomeService() }`, we are providing a _value_, which is the service instance and the token is the class. If we use `useClass`, then Angular expects a class, that it will try to instantiate itself. – Paul Samsotha Dec 18 '16 at 05:21
  • I think [this post](http://stackoverflow.com/a/40019237/2587435) might provide some more clarification also – Paul Samsotha Dec 18 '16 at 05:22