Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
664 views
in Technique[技术] by (71.8m points)

angular - How do I inject a parent component into a child component?

I'm trying to inject a parent component into a child component. I thought this would be straightforward – simply specify/inject the parent component in the child's constructor():

constructor(private _parent:AppComponent) {}   // child component constructor

I get the following error:

EXCEPTION: Cannot resolve all parameters for ChildComponent(?). Make sure they all have valid type or annotations.

What am I missing?

ChildComponent:

import {Component} from 'angular2/core';
import {AppComponent} from './app.component';

@Component({
  selector: 'child',
  template: `<p>child</p>`
})
export class ChildComponent {
  constructor(private _parent:AppComponent) {}
}

AppComponent:

import {Component} from 'angular2/core';
import {ChildComponent} from './child.component';

@Component({
  selector: 'my-app',
  template: `{{title}} <child></child>
  `,
  directives: [ChildComponent]
})
export class AppComponent {
  title = "Angular 2 - inject parent";
  constructor() { console.clear(); }
}

Plunker

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

See @EricMartinez's comment for the answer. The problem seems to be a circular reference when A imports B and B imports A.

Here's a plunker that uses two files instead of the one file that is in Eric's plunker.

The only change from my original plunker is in the ChildComponent:

import {Component, Inject, forwardRef} from 'angular2/core';
// ....
constructor(@Inject(forwardRef(() => AppComponent)) private _parent:AppComponent)

I don't know for sure if this eliminates the circular reference, since A and B are still importing each other, but it seems to work.

See also https://github.com/angular/angular/issues/3216, where Mi?ko states:

This [not user-friendly declaration using forwardRef()] is a limitation of JS and how the function declarations get hoisted. Whenever you have a circular dependency you will need forwardRef :-( I just don't see a away around it.

I would argue that you should not be in situation where your parent needs to know about the children and children need to know about parent. @Query should take care of most of the use cases.

I am sorry, but while I agree this is a pain in some rare cases, I don't see a way out of it, and hence this issue is not actionable, will close.

Hmm... the reason I tried injecting the parent was because I see two ways for a child to communicate with a parent:

  1. the child defines output properties and emits events, which the parent subscribes to
  2. the child injects the parent (e.g., Pane might inject Tabs) and can then call methods on the parent

And I was trying to determine when to use each approach. Mi?ko makes it sound like 2. should be rare.

Update: I was thinking about this some more... 1. is better because there is less coupling between the child and the parent. With 1. the child doesn't need to know (and probably shouldn't know) the public API/interface of the parent.
In the reverse direction (e.g., the parent uses @ViewChild (@Query is now deprecated) to get a reference to the child, then calls methods on the child), the coupling is fine, because the parent is using the child component, so it needs to know the public API/interface of the child: i.e., the input and output properties and public methods.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...