Reputation: 210
This is proably a special case (injecting the browsers native window object), but nevertheless I'm a bit confused about why I still need the @Inject() parameter-decorator when my class already has a @Injectable() decorator.
Take this simplified example:
import { provide, bootstrap, Injectable, Inject } from '@angular/core';
@Injectable()
export class Token {
private token: string;
public constructor(token: string, window: Window) {
this.token = window.atob(token);
};
public getToken(): string {
return this.token;
}
}
@Injectable()
export class TokenFactory {
private window: Window;
public constructor(window: Window) {
this.window = window;
}
public createToken(token: string): Token {
return new Token(token, this.window);
}
}
@Component({
template: `
<p *ngFor="let token of tokens">
Encoded: {{token.getToken()}}
</p>
`,
providers: [ TokenFactory ]
})
class MainComponent {
public tokens: Token[];
public constructor(factory: TokenFactory) {
this.tokens = [
factory.create('token-1'),
factory.create('token-2')
];
};
}
bootstrap(
MainComponent, [
provide(Window, { useValue: window })
]);
Overview: We have a token class that represents an object that could exist multiple times inside a component or another service (so no singleton). The token class depends on the global window object (eg. for base64 encoding). To make this testable we define an app-wide provider for the global window object during bootstrap instead of using it directly in the token service.
The main component needs to create tokens dynamically, so we create and inject a simple factory-service TokenFactory which also needs the window provider (to pass it the the token class during construction).
The Problem: This fails when executed in a browser with the error
Can't resolve all parameters for TokenFactory: (?).
but can be fixed by adding a @Inject(Window) decorator to the factories constructor window parameter.
Now, I'm a bit confused, since most guides/tutorials explain that the inject decorator is not required in typescript when decorating the class with the Injectable decorator, so why does the example fail without using @Inject() decorator?
Config: emitDecoratorMetadata and experimentalDecorators settings are enabled and I'm using tsc 1.8.10 and angular2 rc.3.
PS: I'm also open for general design improvements.
(Eg. In a production scenario I would probably only export the Token interface and not the whole class)
Upvotes: 2
Views: 2212
Reputation: 657308
It's unclear to me what the question actually is about but
type string
for a constructor parameter of an injectable doesn't make any sense without @Inject(...)
@Injectable()
export class Token {
private token: string;
public constructor(token: string, window: Window) { // <<== invalid
this.token = window.atob(token);
};
public getToken(): string {
return this.token;
}
}
but because you are using it like
new Token(token, this.window);
it seems that just @Injectable()
should be removed from this class.
About the error message: It looks like Window
is not properly imported or it is not a type but an OpaqueToken
or a string
.
@Inject()
is required if a key that differs from the parameter type should be used by dependency injection. In your case it looks like Window
is not a type (class) and therefore doesn't work when used as such.
Upvotes: 5