2016-03-15 5 views
18

В Angular 2 у меня есть компонент, который имеет дочерний компонент. Тем не менее, я хочу получить копию этого дочернего компонента для использования в родительском, для вызова его функций или чего-то еще.Получение ссылки на дочерний компонент в родительском компоненте

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

Я нашел способ сделать это, вот ребенок код:

//our child 
import {Component, OnInit, EventEmitter} from 'angular2/core' 

@Component({ 
    selector: 'my-child', 
    providers: [], 
    template: ` 
    <div> 
     <h2>Child</h2> 

    </div> 
    `, 
    directives: [], 
    outputs: ['onInitialized'] 
}) 

export class Child implements OnInit{ 

    onInitialized = new EventEmitter<Child>(); 

    constructor() { 
    this.name = 'Angular2' 
    } 

    ngOnInit() { 
    this.onInitialized.emit(this); 
    } 
} 

Родитель:

//our root app component 
import {Component} from 'angular2/core' 
import {Child} from './child' 

@Component({ 
    selector: 'my-app', 
    providers: [], 
    template: ` 
    <div> 
     <h2>Hello {{name}}</h2> 
     <my-child (onInitialized)="func($event)"></my-child> 
    </div> 
    `, 
    directives: [Child] 
}) 
export class App { 
    constructor() { 
    this.name = 'Angular2' 
    } 

    func(e) { 
    console.log(e) 

    } 
} 

Я реализовал его здесь, в этом plunker: http://plnkr.co/edit/e3pEn9Hd54q1mijNGDpR?p=preview

Но похоже, взломать, нет ли более простого способа привязать компонент к переменной в ее родительском?

+0

Какой конкурс на ответ ... :) – eesdil

+0

hahahah .... вы наблюдали это, по крайней мере! – micronyks

+0

Как уже упоминалось в ответах, вы можете использовать @ViewChild, который обсуждается в поваренной книге Component Interaction: https://angular.io/docs/ts/latest/cookbook/component-communication.html#!#parent-to -view-child –

ответ

36

Вы можете использовать ViewChild

<child-tag #varName></child-tag> 

@ViewChild('varName') someElement; 

ngAfterViewInit() { 
    someElement... 
} 

где varName переменная шаблона добавляется к элементу. В качестве альтернативы вы можете запрашивать тип компонента или директивы.

Есть альтернативы, как ViewChildren, ContentChild, ContentChildren

@ViewChildren также могут быть использованы в конструкторе

constructor(@ViewChildren('var1,var2,var3') childQuery:QueryList) 

Преимущество заключается в том, что результат доступен ранее.

Так и http://www.bennadel.com/blog/3041-constructor-vs-property-querylist-injection-in-angular-2-beta-8.htm для некоторых преимуществ/недостатков использования конструктора или поля.

Примечание: @Query() является устаревшим предшественником @ContentChildren()

Update

Query в настоящее время только абстрактный базовый класс. Я не нашел, если он используется на всех https://github.com/angular/angular/blob/2.1.x/modules/@angular/core/src/metadata/di.ts#L145

+1

Благодарим вас за ответ. Просто вопрос, чтобы убедиться, что мои компоненты рекурсивные, у ребенка будут дети и т. Д. И т. Д. Получает ли ViewChildren все рекурсивное дерево? или только первый уровень (тот, который находится внутри фактического шаблона)? –

+1

Кроме того, некоторые компоненты включены с помощью ngIf, поэтому они не появляются сразу же после создания родителя, что-нибудь изменит? –

+0

Элементы AFAIK содержатся в QueryList, когда они действительно существуют в DOM. Когда ngIf является ложным, оно удаляется из списка. –

1

Вы можете фактически пойти с ViewChild API ...

родителя.TS

<button (click)="clicked()">click</button> 

export class App { 
    @ViewChild(Child) vc:Child; 
    constructor() { 
    this.name = 'Angular2' 
    } 

    func(e) { 
    console.log(e) 

    } 
    clicked(){ 
    this.vc.getName(); 
    } 
} 

child.ts

export class Child implements OnInit{ 

    onInitialized = new EventEmitter<Child>(); 
    ... 
    ... 
    getName() 
    { 
    console.log('called by vc') 
    console.log(this.name); 
    } 
} 
+0

Ссылка на плункер, похоже, сломана - она ​​открывает исходный план ... Привет, мир ... –

+1

@ 9ilsdx9rvj0lo Обновлена ​​ссылка для вашей справки. Теперь это работает. вы можете проверить это сейчас. – micronyks

3

Вы должны использовать в @ViewChild декоратора для ссылки на компонент ребенка от родителя одной инъекцией:

import { Component, ViewChild } from 'angular2/core'; 

(...) 

@Component({ 
    selector: 'my-app', 
    template: ` 
    <h1>My First Angular 2 App</h1> 
    <child></child> 
    <button (click)="submit()">Submit</button> 
    `, 
    directives:[App] 
}) 
export class AppComponent { 
    @ViewChild(Child) child:Child; 

    (...) 

    someOtherMethod() { 
    this.searchBar.someMethod(); 
    } 
} 

Вот обновленный plunkr: http://plnkr.co/edit/mrVK2j3hJQ04n8vlXLXt?p=preview.

Вы можете заметить, что декоратор @Query параметр также может быть использован:

export class AppComponent { 
    constructor(@Query(Child) children:QueryList<Child>) { 
    this.childcmp = children.first(); 
    } 

    (...) 
} 
Смежные вопросы