En Angular 2, tengo un componente que tiene un componente secundario. Sin embargo, quiero adquirir una copia de ese componente secundario para usar en el componente principal, para llamar a sus funciones o lo que sea.
Descubrí que podía usar variables locales y de esa manera podré usar el componente en la plantilla. Sin embargo, no solo lo uso en la plantilla, quiero usarlo en el código real del componente.
Encontré una manera de hacerlo, aquí está el código secundario:
//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); } }Padre:
//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) } }Lo implementé aquí en este plunker . Pero parece un truco.
¿No hay una forma más sencilla de adjuntar el componente a una variable en su padre?
Puedes usar ViewChild
<child-tag #varName></child-tag> @ViewChild('varName') someElement; ngAfterViewInit() { someElement... } donde varName es una variable de plantilla agregada al elemento. Alternativamente, puede consultar por componente o tipo de directiva.
Hay alternativas como ViewChildren , ContentChild , ContentChildren .
@ViewChildren también se puede usar en el constructor.
constructor(@ViewChildren('var1,var2,var3') childQuery:QueryList)La ventaja es que el resultado está disponible antes.
Consulte también http://www.bennadel.com/blog/3041-constructor-vs-property-querylist-injection-in-angular-2-beta-8.htm para conocer algunas ventajas/desventajas de usar el constructor o un campo.
Nota: @Query() es el predecesor en desuso de @ContentChildren()
Actualizar
Query es actualmente solo una clase base abstracta. No he encontrado si se usa en absoluto https://github.com/angular/angular/blob/2.1.x/modules/@angular/core/src/metadata/di.ts#L145
Debe aprovechar el decorador @ViewChild para hacer referencia al componente secundario del principal mediante inyección:
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(); } }Aquí está el plunkr actualizado: http://plnkr.co/edit/mrVK2j3hJQ04n8vlXLXt?p=preview .
Puede notar que el decorador de parámetros @Query también podría usarse:
export class AppComponent { constructor(@Query(Child) children:QueryList<Child>) { this.childcmp = children.first(); } (...) }En realidad, puede ir con ViewChild API ...
padre.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(); } }niño.ts
export class Child implements OnInit{ onInitialized = new EventEmitter<Child>(); ... ... getName() { console.log('called by vc') console.log(this.name); } }