2

I'm messing around with Angular2 and I'm wanting the ability to inject one component into another based on the bootstrapped bindings.

class HelloComponent {
    name: string;
}

@Component({
    selector: 'hello'
}
@View({
    template: `<h3>Hello {{ name }}</h3>`
})
class HelloBobComponent extends HelloComponent {
    constructor() {
        this.name = 'Bob';
    }
}

@Component({
    selector: 'app'
}
@View({
    directives: [HelloComponent]
    template: `<h1>Welcome to my Angular2 app</h1>
                <hello></hello>`
}
class AppComponent {
}

bootstrap(AppComponent, [
    bind(HelloComponent).toClass(HelloBobComponent)
]);

Here I'm using HelloComponent as a token that I want Angular2's Injector to resolve HelloBobComponent. I'm doing this so that I can swap components in and out based on the current app configuration. The above example obviously doesn't work. Is this possible using one of the frameworks decorators? I haven't found an answer yet digging though blogs or the source.

edit: To clarify, how do I get the directives property on the View decorator to treat HelloComponent as a di token instead of a type.

Stacy Gay
  • 101
  • 10
  • 1
    See if this [answer](https://gitter.im/angular/angular?at=55fabc7f6f976dff036eeb79) your question, somebody asked in the chatroom. Read from there to @pkozlowski's answer. – Eric Martinez Sep 17 '15 at 16:38
  • Thanks for pointing me in this direction. I have tinkered and found that I can bind explicitly in the component using directives: [bind(HelloComponent).toClass(HelloBobComponent)]. This doesn't help me however as I want to resolve from the root injector so I don't have to worry about configuring the binding in the individual components. – Stacy Gay Sep 17 '15 at 17:14

1 Answers1

0

This is currently not supported as of alpha37. The compiler resolves directives passed in the View decorator by either type or binding but does not look up from the parent injector.

For example:

@View({
  url: '...',
  directives: [
    Directive1,
    bind(Directive2).toClass(Directive2Impl),
  ]
}) 

The intention for the "directives" property here was only to prevent selector naming collision. Later bind support was added to aid in testing.

The only solution I can think of without editing the compiler function would be to maintain an external Injector and resolve types on component declaration.

Stacy Gay
  • 101
  • 10
  • I've continued to struggle with this throughout the betas. I did have some initial luck with overriding the DirectiveResolver that took a dependency on the root injector to resolve an alternate directive based on the DirectiveMetadata. This was broken once they introduced the ReflectveInjector and even further once they started to optimize the compiler. The nail in the coffin will be with the view compiler which precompiles components. My solution is to maintain a directive registry which is just an object of key/directive pairs. directives:[registry.resolveDirective(someDirectiveToken)] – Stacy Gay Jul 08 '16 at 02:12