2016-02-29 3 views
8

В Угловом 2 дочерний компонент может получить свой родительский компонент, введенный через параметр конструктора. Пример:Вставить родительский компонент того же типа, что и дочерний компонент

@Component({...}) 
export class ParentComponent { 
    ... 
} 

@Component({...}) 
export class ChildComponent { 
    constructor(private parent: ParentComponent) { } 
    ... 
} 

Это работает красиво и хорошо, и как только родитель и ребенок имеют разные типы.

Однако другой типичный пример использования - это древовидная структура, в которой каждый узел дерева отображается как отдельный компонент. Что нам делать, если каждый из компонентов узла дерева должен иметь доступ к его родительскому объекту? Я попытался это:

@Component({...}) 
export class TreeNodeComponent { 
    constructor(private parent: TreeNodeComponent) { } 
... 
} 

Но это терпит неудачу за исключением следующего выполнения:

EXCEPTION: Cannot instantiate cyclic dependency! 

Я думаю, причина в том, что Угловое 2 впрыскивает сам компонент, а не его родительский компонент.

Как определить угловое значение для инкорпорации компонента компонента, даже если они одного типа?

Plunkerhttps://plnkr.co/edit/ddvupV?p=preview

+0

Почему вы вставляете родителя, почему бы просто не использовать привязку данных? –

+0

Попробуйте этот: http://stackoverflow.com/questions/34540615/how-do-i-inject-a-parent-component-into-a-child-component – Damitha

ответ

15

Таким образом, он работает

constructor(@SkipSelf() @Host() @Optional() parent: TreeNodeComponent) {} 

Plunker

  • @SkipSelf(), чтобы не получить себе инъекции, которые будут применяться, если TreeNodeComponent запрашивается
  • @Host() не смотрите дальше, чем элемент-хост
  • @Optional() ?? нет родительского TreeNodeComponent для корневого узла

Смотрите также http://blog.thoughtram.io/angular/2015/08/20/host-and-visibility-in-angular-2-dependency-injection.html

+0

Ее плункер: [link] (https: //plnkr.co/edit/ddvupV?p=preview). Прочтите комментарий в treenode.component. – user928437

+0

Я понимаю ваш комментарий о стратегии, и я полностью согласен. Вместо этого он использовал бы привязку в случае такой древовидной структуры. Мой фактический вариант использования отличается. Я просто использовал узлы дерева в качестве примера, чтобы проиллюстрировать основной вызов, поскольку древовидная структура является хорошо известной концепцией. – user928437

+0

Я не смог заставить его работать, также не с подходом Тьерриса. Я считаю это ошибкой. –

0

Angular2 выглядит в текущий инжектор для поставщика. В вашем случае TreeNodeComponent соответствует самому компоненту.

Экземпляр родительского компонента расположен в исходном инжекторе.

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

@Component({ 
    (...) 
}) 
export class TreeNodeComponent { 
    constructor(injector:Injector) { 
    let parentInjector = injector.parent; 
    let parent = patentInjector.get(TreeNodeComponent); 
    } 
} 

Смотрите эту ссылку для документации класса Injector:

То есть, я думаю, что Гюнтер Комментарий о связывании и общий сервис особенно релевантные ...

0

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

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

Однако мой фактический прецедент (что более сложно объяснить) заключается в том, что я хочу разработать расширенное раскрывающееся меню. Требования:

  • Раскрывающийся должны иметь произвольное количество уровней (меню, подменю, subsubmenu и т.д.)
  • Раскрывающийся определяется во время разработки - его содержание не основано на динамических данных.
  • Должно быть возможным привязать обработчики событий (_) = к каждому выпадающему элементу.
  • Должно быть возможно вставить компоненты пользовательского контроля в раскрывающийся список.

пример использования:

<dropdown label="Actions"> 
    <dropdown-item label="Action 1" (click)="action1()"></dropdown-item> 
    <dropdown-item label="Action 2" (click)="action2()"></dropdown-item> 
    <dropdown-item label="Submenu"> 
    <dropdown-item label="Action 3.1" (click)="action31()"></dropdown-item> 
    <dropdown-item label="Action 3.2"> 
     <dropdown-slider (change)="changeHandler()"></dropdown-slider> 
    </dropdown-item> 
    <dropdown-item label="Submenu"> 
     <dropdown-item label="Action 3.3.1" (click)="action331()"></dropdown-item> 
     <dropdown-item label="Action 3.3.2" (click)="action332()"></dropdown-item> 
    </dropdown-item> 
    </dropdown-item> 
</dropdown>  

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

Но я, возможно, ошибаюсь! Любые мнения об этом приветствуются!

+0

Это не похоже на ответ. Я думаю, было бы лучше отредактировать ваш вопрос и добавить туда этот контент. –

+0

Почему вы вообще вводите родителя? Какие члены вы хотите получить от родителя? –

+0

Мне нужно ввести родителя, потому что открытие пункта меню должно закрыть всех братьев и сестер, чтобы одновременно открывался только один «путь к меню». Чтобы достичь этого, я должен иметь возможность ссылаться на родительский компонент. – user928437

Смежные вопросы