In Angular 2, I have a component that has a child component. However, I want to acquire a copy of that child component to use in the parent, to call its functions or whatever.
I found out that I could use local variables, and that way I will be able to use the component in the template. However, I don't to only use it in the template, I want to use it in the actual code of the component.
I found a way to do that, here is the child code:
//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); } }
Parent:
//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) } }
I implemented it here in this plunker. But it seems like a hack.
Isn't there a simpler way to attach the component to a variable in its parent?
We can get child component values in the parent component by creating a reference to the child component using the @ref directive in the Parent component. Using the reference instance, you can access the child component values in the parent.
To pass data from child to parent component in React:Pass a function as a prop to the Child component. Call the function in the Child component and pass the data as arguments. Access the data in the function in the Parent .
@Input() and @Output() give a child component a way to communicate with its parent component. @Input() lets a parent component update data in the child component. Conversely, @Output() lets the child send data to a parent component.
You can use ViewChild
<child-tag #varName></child-tag> @ViewChild('varName') someElement; ngAfterViewInit() { someElement... }
where varName
is a template variable added to the element. Alternatively, you can query by component or directive type.
There are alternatives like ViewChildren
, ContentChild
, ContentChildren
.
@ViewChildren
can also be used in the constructor.
constructor(@ViewChildren('var1,var2,var3') childQuery:QueryList)
The advantage is that the result is available earlier.
See also http://www.bennadel.com/blog/3041-constructor-vs-property-querylist-injection-in-angular-2-beta-8.htm for some advantages/disadvantages of using the constructor or a field.
Note: @Query()
is the deprecated predecessor of @ContentChildren()
Update
Query
is currently just an abstract base class. I haven't found if it is used at all https://github.com/angular/angular/blob/2.1.x/modules/@angular/core/src/metadata/di.ts#L145
You need to leverage the @ViewChild
decorator to reference the child component from the parent one by injection:
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(); } }
Here is the updated plunkr: http://plnkr.co/edit/mrVK2j3hJQ04n8vlXLXt?p=preview.
You can notice that the @Query
parameter decorator could also be used:
export class AppComponent { constructor(@Query(Child) children:QueryList<Child>) { this.childcmp = children.first(); } (...) }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With