Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62
Subscribe to my email list now at http://jauyeung.net/subscribe/
Angular is a popular front-end framework made by Google. Like other popular front-end frameworks, it uses a component-based architecture to structure apps.
In this article, we’ll look at some examples of Angular component interaction.
Pass Data From Parent to Child with Input Binding
We can pass data from a parent component to a child component by using the @Input
operator in the child component.
For example, we can write the following to do that:
app.module.ts
:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { PersonComponent } from './person/person.component';
@NgModule({
declarations: [
AppComponent,
PersonComponent
],
imports: [
BrowserModule,
AppRoutingModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
app.component.ts
:
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
person = { name: 'Jane' }
}
app.component.html
:
<app-person [person]='person'></app-person>
person.component.ts
:
import { Component, Input } from '@angular/core';
@Component({
selector: 'app-person',
templateUrl: './person.component.html',
styleUrls: ['./person.component.css']
})
export class PersonComponent {
@Input() person;
}
person.component.html
:
<p>{{person.name}}</p>
In the code above, we have the AppComponent
, which is the parent of PersonComponent
.
In AppComponent
, we have the person
field, which is passed into the person
property of app-person
.
Then in the PersonComponent
, we have:
@Input() person;
to get the person
input value that’s passed in. Then we display the name
property with:
<p>{{person.name}}</p>
in the template.
Then we should see ‘Jane’ on the screen.
Intercept Input Property Changes With a Setter
We can add a setter to the @Input
decorator to intercept the value that’s set and change it to something else.
For example, we can write the following code:
app.component.ts
:
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
person = { name: 'Jane' }
}
app.component.html
:
<app-person [person]='person'></app-person>
<app-person [person]='undefined'></app-person>
person.component.ts
:
import { Component, Input } from '@angular/core';
@Component({
selector: 'app-person',
templateUrl: './person.component.html',
styleUrls: ['./person.component.css']
})
export class PersonComponent {
private _person = {};
@Input()
set person(person) {
this._person = person || { name: 'Foo' };
}
get person() { return this._person; }
}
person.component.html
:
<p>{{person.name}}</p>
In the code above, we added getters and setters for the person
property in the PersonComponent
.
In the setter, we set person
depending if person
is defined or not. If it’s not then we set this._person
to a default object. Otherwise, we set this._person
to whatever the value is passed in from the parent.
In the getter, we get the person
value that was set by return this._person
.
The first line should display ‘Jane’ since we passed in person
into app-person
.
The second line should display ‘Foo’ since we pass undefined
as the value of person
.
Intercept Input Property Changes with ngOnChanges()
We can use ngOnChanges
to intercept the change and then set the value passed into the @Input
field by changing it to what we want.
For example, we can write the following code:
app.component.ts
:
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
person = { name: 'Jane' }
}
app.component.html
:
<app-person [person]='person'></app-person>
<app-person [person]='undefined'></app-person>
person.component.ts
:
import { Component, Input, SimpleChange } from '@angular/core';
@Component({
selector: 'app-person',
templateUrl: './person.component.html',
styleUrls: ['./person.component.css']
})
export class PersonComponent {
@Input() person;
ngOnChanges(change: { [propKey: string]: SimpleChange }) {
this.person = change.person.currentValue || { name: 'Foo' };
}
}
person.component.html
:
<p>{{person.name}}</p>
In the code above, we have the ngOnChanges
hook in the PersonComponent
.
It takes a change
parameter that has the value of the change. In the hook, we check if change.person.currentValue
is defined.
If it’s not, then we set this.person
to { name: ‘Foo’ }
. Otherwise, we set this.person
to change.person.currentValue
.
Then we should see the same thing as in the first example.
Parent Listens for Child Event
We can call emit
on an EventEmitter in the child component and then listen to the emitted event in the parent.
For instance, we can do that as follows:
app.component.ts
:
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
person = {};
}
app.component.html
:
<app-person (emittedPerson)='person = $event'></app-person>
<p>{{person.name}}</p>
person.component.ts
:
import { Component, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'app-person',
templateUrl: './person.component.html',
styleUrls: ['./person.component.css']
})
export class PersonComponent {
@Output() emittedPerson = new EventEmitter(); emitPerson() {
this.emittedPerson.emit({ name: 'Jane' });
}
}
person.component.html
:
<button (click)='emitPerson()'>Get Person</button>
In the code above, we have the emitPerson
method in the PersonComponent
, which calls emit
on the emittedPerson
emitter, where we pass in the payload to send to the parent.
Then in app.component.html
, we have:
<app-person (emittedPerson)='person = $event'></app-person>
to listen to the emittedPerson
event from app-person
and then set the person
field to the $event
variable passed in from the child by calling emit
.
Then we have:
<p>{{person.name}}</p>
to display the name
property value from the emitted object.
Therefore, when we click the Get Person button, we should see ‘Jane’ displayed.
Conclusion
We can pass data from a parent to a child by using the @Input
decorator in the child.
To pass data from a child to a parent, we can emit an event from the child. Then the parent can listen to it and then run code to do something with it.
$event
has the object that’s passed in with the emit
call.