I'm trying to get a very basic, functional structure set up for Angular 2. It will have only the most basic API elements so that as the framework advances, I can advance my structure.
Currently, I'm at my wit's end as to how to perform the simple act of passing services. Here is some example source, taken right from the ments of the most recent DefinitelyTyped file:
class Greeter {
greet(name: string) {
return 'Hello ' + name + '!';
}
}
@Component({
selector: 'greet',
appInjector: [Greeter]
})
@View({
template: `{{greeter.greet('world')}}!`
})
class HelloWorld {
greeter: Greeter;
constructor(greeter: Greeter) {
this.greeter = greeter;
}
}
bootstrap(HelloWorld);
As you can see, I'm using Typescript 1.5 in this example.
I have tried to inject the Greeting
service in the Component annotation using hostInjector
, injectibles
and appInjector
. I've also tried adding it to the second argument of the bootstrap call, as in bootstrap(HelloWorld, [Greeter])
.
In all cases I get this error message when trying to run it in the browser:
Error during instantiation of Token(ComponentRef)!. ORIGINAL ERROR: Cannot resolve all parameters for HelloWorld(?). Make sure they all have valid type or annotations.
Of course, if I remove greeter: Greeter
argument from the constructor, the error in question goes away and is replaced by other, expected errors further down the chain.
Ideas?
EDIT
I updated the title of this question to specify that I am using TypeScript 1.5
I'm trying to get a very basic, functional structure set up for Angular 2. It will have only the most basic API elements so that as the framework advances, I can advance my structure.
Currently, I'm at my wit's end as to how to perform the simple act of passing services. Here is some example source, taken right from the ments of the most recent DefinitelyTyped file:
class Greeter {
greet(name: string) {
return 'Hello ' + name + '!';
}
}
@Component({
selector: 'greet',
appInjector: [Greeter]
})
@View({
template: `{{greeter.greet('world')}}!`
})
class HelloWorld {
greeter: Greeter;
constructor(greeter: Greeter) {
this.greeter = greeter;
}
}
bootstrap(HelloWorld);
As you can see, I'm using Typescript 1.5 in this example.
I have tried to inject the Greeting
service in the Component annotation using hostInjector
, injectibles
and appInjector
. I've also tried adding it to the second argument of the bootstrap call, as in bootstrap(HelloWorld, [Greeter])
.
In all cases I get this error message when trying to run it in the browser:
Error during instantiation of Token(ComponentRef)!. ORIGINAL ERROR: Cannot resolve all parameters for HelloWorld(?). Make sure they all have valid type or annotations.
Of course, if I remove greeter: Greeter
argument from the constructor, the error in question goes away and is replaced by other, expected errors further down the chain.
Ideas?
EDIT
I updated the title of this question to specify that I am using TypeScript 1.5
I had a similar problem when using typescript 1.5.0-beta and angular 2.0.0-alpha.28 (not sure if the versions are strictly relevant) with gulp.
You need to tell the typescript piler to export metadata so the DI injector knows what to do. I did this by adding emitDecoratorMetadata
and experimentalDecorators
to my tsconfig.json:
{
"pilerOptions": {
"module": "monjs",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"sourceMap": true,
"target": "es5"
}
}
After that you can add appInjector: [Greeter]
to your @Component
declaration like you've done or to the bootstrap declaration:
bootstrap(HelloWorld, [Greeter]);
Regarding TS2348. I got the same error. Got rid of ComponentAnnotaion and ViewAnnotation and this helped:
import {
bootstrap,
Component,
View
} from 'angular2/angular2';
I hope your code will work fine in typescript 1.5 release. Right now, you should use Inject annotation in typescript 1.5.0-beta.
import {
ComponentAnnotation as Component,
ViewAnnotation as View, bootstrap,
Inject
} from 'angular2/angular2';
@Component({
selector: 'app',
hostInjector: [Service]
})
@View({
template: '{{greeting}} world!'
})
class App {
constructor(@Inject(Service)service: Service) {
this.greeting = service.greeting();
setTimeout(() => this.greeting = 'Howdy,', 1000);
}
}
class Service {
greeting() {
return 'Hello';
}
}
bootstrap(App);
More a workaround than a solution, but if you move your service definition to a separate file (greeting.ts), and import it
import {Greeting} from 'greeting';
then the injector works correctly. This is built using tsc from the mand line (taken from the 5 min quickstart on angular.io)
tsc --watch -m monjs -t es5 --emitDecoratorMetadata app.ts
With angular2.0.0-alpha.32 I acplished this with
/// <reference path="../../typings/angular2/angular2.d.ts" />
import {Component, View, bootstrap, NgFor} from 'angular2/angular2';
import {MyService} from 'js/services/MyService';
// Annotation section
@Component({
selector: 'my-app',
viewInjector: [MyService]
})
@View({
templateUrl: 'templates/my-app.tpl.html',
directives: [NgFor]
})
class MyComponent {
mySvc:MyService;
constructor(mySvc:MyService) {
this.mySvc = mySvc;
}
onInit() {
this.mySvc.getData();
}
}
bootstrap(MyComponent, [MyService]);
Here is the code, straight out of the plnkr.co template for injecting a service http://plnkr.co/edit/m5sHWWFmgYPrfsMv0u2r
import {
ComponentAnnotation as Component,
ViewAnnotation as View, bootstrap
} from 'angular2/angular2';
@Component({
selector: 'app',
viewInjector: [Service]
})
@View({
template: '{{greeting}} world!'
})
class App {
constructor(service: Service) {
this.greeting = service.greeting();
setTimeout(() => this.greeting = 'Howdy,', 1000);
}
}
class Service {
greeting() {
return 'Hello';
}
}
bootstrap(App);