1
votes

In Angular2 it's possible to inject an parent or even ancestor (eg. grandparent) component to child by simply using the following syntax:

export class Grandchild {
   constructor( @Optional() @Host() @Inject(forwardRef(() => Ancestor)) ancestor)
}

However, that seems to work only for ancestor-grandchild relations that are defined in a single template, like following:

<!-- App component template -->
<ancestor>
  <foobar>
    <grandchild></grandchild>  <!-- injection works -->
  </foobar>
</ancestor>

If, instead our templates would be like as follows, the injection will not work:

<!-- App component template -->
<ancestor>
  <foobar></foobar>
</ancestor>

<!-- Foobar component template -->
<grandchild></grandchild>  <!-- injection doesn't work -->

I have made a plunker for this: http://plnkr.co/edit/D9iSokONIAFAS8G1NTd1

2
I don't think that is supported. - Günter Zöchbauer
I hope that's not the case, but if so, then I think I should file a bug report to Angular2. - Risto Välimäki
As far as I know only the direct parent can be injected. You can provide a service at the grandparent that can be injected by any descendant. I'm pretty sure a bug report is redundant. - Günter Zöchbauer
That idea for using a service provided by grandparent could be the key. Though there is a problem with the "Optional" part then, though that's possible to overcome with another hack. Probably you should modify your comment as an answer? - Risto Välimäki

2 Answers

1
votes

You can provide a shared service and use it to communicate.

@Injectable()
class SharedService {
  grandParent = new BehaviorSubject();
}

@Component({
  selector: 'grand-parent',
  providers: [SharedService],
  ...
})
class GrandParent {
  constructor(sharedService:SharedService) {
    sharedService.grandParent.next(this);
  }
}

@Component({
  selector: 'descendant',
  providers: [],
  ...
})
class Descendant {
  constructor(@Optional() sharedService:SharedService) {
    if(sharedService) {
      sharedService.grandParent.subscribe(grandParent => this.grandParent = grandParent);
    }
  }
}

In practice I wouldn't send a reference to this but use observables to send messages the receiver acts on.

0
votes

Keith Richards could tell you a thing or two about ingesting ancestors...

https://www.youtube.com/watch?v=uo5dtPx7P8g

Sorry, cheap joke but had to do it.