Подтвердить что ты не робот

Как добавить родительский компонент в дочерний компонент?

Я пытаюсь ввести родительский компонент в дочерний компонент. Я думал, что это будет просто. просто укажите/вставьте родительский компонент в дочерний элемент constructor():

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

Я получаю следующую ошибку:

ИСКЛЮЧЕНИЕ: Не удается разрешить все параметры для ChildComponent (?). Убедитесь, что все они имеют допустимый тип или аннотации.

Что мне не хватает?

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

4b9b3361

Ответ 1

См. @EricMartinez comment для ответа. Проблема кажется циклической ссылкой, когда A импортирует B и B импортирует A.

Здесь plunker, который использует два файла вместо одного файла, который находится в Эрик плункер.

Единственное изменение моего исходного плункера - в ChildComponent:

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

Я не знаю наверняка, если это исключает циклическую ссылку, так как A и B все еще импортируют друг друга, но, похоже, это работает.

См. также https://github.com/angular/angular/issues/3216, где Мишко утверждает:

Это [непригодное для пользователя объявление с использованием forwardRef()] является ограничением JS и тем, как объявляются объявления функций. Всякий раз, когда у вас есть круговая зависимость, вам понадобится forwardRef:-( Я просто не вижу вокруг себя.

Я бы сказал, что вы не должны находиться в ситуации, когда ваш родитель должен знать о том, что дети и дети должны знать о родителях. @Query должен позаботиться о большинстве случаев использования.

Прошу прощения, но пока я согласен, что это боль в некоторых редких случаях, я не вижу выхода из этого, и, следовательно, эта проблема не подлежит действию, будет закрыта.

Хм... причина, по которой я пыталась вставить родителя, заключалась в том, что я вижу два способа для ребенка связаться с родителем:

  • ребенок определяет выходные свойства и испускает события, которые родитель подписывает
  • ребенок вводит родителя (например, Pane может вводить вкладки), а затем может вызывать методы родительского

И я пытался определить, когда использовать каждый подход. Мишко делает это, как будто 2. должно быть редко.

Обновление: Я думал об этом еще немного... 1. лучше, потому что между ребенком и родителем меньше связи. С 1. ребенку не нужно знать (и, вероятно, не знать) открытый API/интерфейс родителя.
В обратном направлении (например, родитель использует @ViewChild (@Query теперь устарел), чтобы получить ссылку на дочерний элемент, затем вызывает методы для дочернего элемента), связь прекрасна, поскольку родитель использует дочерний компонент, поэтому он должен знать общедоступный API/интерфейс дочернего элемента: то есть свойства ввода и вывода и общедоступные методы.