I have a nested child component like this:
The best way to access a child component is @ViewChild.
Let's say you have AppMainComponent with a nested ChildComponent from your example.
// app-main.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-main',
template: `
<child-component />
`
})
export class AppMainComponent {}
You want to invoke a clear method from your ChildComponent.
// child.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'child-component',
template: '{{ greeting }}'
})
class ChildComponent {
greeting: String = 'Hello World!';
clear() {
this.greeting = null;
}
}
You can accomplish it by importing the ChildComponent class, ViewChild decorator and pass component's class in it as a query. This way, you would have access to the ChildComponent's interface stored in the custom variable. Here is an example:
// app-main.component.ts
import { Component, ViewChild } from '@angular/core';
import { ChildComponent } from './components/child/child.component';
@Component({
selector: 'app-main',
template: `
<child-component />
`
})
class ChildComponent {
@ViewChild(ChildComponent)
child: ChildComponent;
clearChild() {
this.child.clear();
}
}
Notice! Child view becomes available only after ngAfterViewInit.
Respond after Angular initializes the component's views and child views. Called once after the first ngAfterContentChecked(). A component-only hook.
If you want to execute method automatically, you need to do it inside this lifecycle hook.
You can also get a QueryList of child components via ViewChildren decorator.
import { Component, ViewChildren, QueryList } from '@angular/core';
import { ChildComponent } from './components/child/child.component';
...
@ViewChildren(ChildComponent)
children: QueryList<ChildComponent>;
QueryList might be very useful, e.g. you can subscribe for children changes.
It's also possible to create template reference variables and get access to them via the ViewChild decorator.
Being a son component
@Component({
// configuration
template: `{{data}}`,
// more configuration
})
export class Son {
data: number = 3;
constructor() { }
updateData(data:number) {
this.data = data;
}
}
Having a father component
@Component({
// configuration
})
export class Parent {
@ViewChild(Son) mySon: Son;
incrementSonBy5() {
this.mySon.updateData(this.mySon.data + 5);
}
}
In the father's template
<son></son>
<button (click)="incrementSonBy5()">Increment son by 5</button>
This solution only works for one <son></son>
instance in the parent template. If you have more than one instance only will work in the first one of the template.
Parent and child can communicate via data binding.
Example:
@Component({
selector: 'child-component',
inputs: ['bar'],
template: `"{{ bar }}" in child, counter {{ n }}`
})
class ChildComponent{
constructor () {
this.n = 0;
}
inc () {
this.n++;
}
}
@Component({
selector: 'my-app',
template: `
<child-component #f [bar]="bar"></child-component><br>
<button (click)="f.inc()">call child func</button>
<button (click)="bar = 'different'">change parent var</button>
`,
directives: [ChildComponent]
})
class AppComponent {
constructor () {
this.bar = 'parent var';
}
}
bootstrap(AppComponent);
Demo
#f
creates a reference to the child component and can be used in template or passed to function. Data from parent can be passed by [ ]
binding.
You can get a reference to an element using
@ViewChild('childComponent') child;
where childComponent
is a template variable <some-elem #childComponent
>` or
@ViewChild(ComponentType) child;
where ComponentType
is the type of a component or directive and then in ngAfterViewInit
or an event handlers call child.someFunc()
.
ngAfterViewInit() {
console.log(this.child);
}
See also get hold of an element in the template