Categories
Angular JavaScript

Complex Angular Component Interaction Examples

Spread the love

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 complex examples of Angular component interaction.

Parent Interacts with Child Via Local Variable

We can create template reference variable for the child element and then reference that variable within the template to access a child component’s variable in the parent.

For example, we can write the following code:

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 = {};  
}

app.component.html :

<app-person #appPerson></app-person>  
<button (click)='appPerson.setPerson()'>Set Person</button>  
<p>{{appPerson.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 {  
  person = {}; 

  setPerson() {  
    this.person = { name: 'Jane' };  
  }  
}

We left person.component.html blank.

In the code above, we have the PersonComponent , which is the child of AppComponent .

In PeronComponent , we have the person variable and the setPerson method.

Then in app.component.html , we added a #appPerson template variable so that we can access its variable.

Then we used it to call PersonComponent ‘s setPerson method on the Set Person button.

We also displayed appPerson.person.name from PersonComponent in the p element.

When we click the Set Person button, the p tag automatically updates to show the value of appPerson.person.name set by setPerson .

Parent calls an @ViewChild()

In the previous example, we access a child component’s local variables. It’s simple and easy, but it’s limited because the parent-child wiring is all done in the parent.

The parent component has no access to the child.

To access the child component in the parent component’s code, we can use a ViewChild .

To do use ViewChild , we can write the following code:

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, ViewChild } from '@angular/core';  
import { PersonComponent } from './person/person.component';

@Component({  
  selector: 'app-root',  
  templateUrl: './app.component.html',  
  styleUrls: ['./app.component.css']  
})  
export class AppComponent {  
  @ViewChild(PersonComponent, {static: false})  
  private personComponent: PersonComponent;

  setPerson(){  
    this.personComponent.setPerson();  
  }  
}

app.component.html :

<button (click)='setPerson()'>Set Person</button>  
<p>{{personComponent && personComponent.person.name}}</p>  
<app-person></app-person>

person.component.ts :

import { Component } from '@angular/core';

@Component({  
  selector: 'app-person',  
  templateUrl: './person.component.html',  
  styleUrls: ['./person.component.css']  
})  
export class PersonComponent {  
  person = {}; 

  setPerson() {  
    this.person = { name: 'Jane' };  
  }  
}

We left person.component.html blank again.

In the code above, we have the same person and setPerson members in PersonComponent .

Then in in AppComponent , we added the ViewChild as follows:

@ViewChild(PersonComponent, {static: false})  
private personComponent: PersonComponent;

to access the PersonComponent directly from within AppComponent . We need the app-person component in our PersonComponent template even though we don’t show anything in it so that AppComponent can access PersonComponent .

Then we just call the methods directly in AppComponent‘s setPerson method.

Also, we accessed the app-person component within the template with:

<p>{{personComponent && personComponent.person.name}}</p>

to show the person.name property from PersonComponent .

Parent and Children Communicate via a Service

Parent and child components can also communicate via a shared service.

We can create a service and then send the data to an Observable in the service from the child component which the parent component listens to so that it can get the latest data.

To do this, we can write the following:

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';  
import { PersonService } from './person.service';

@NgModule({  
  declarations: [  
    AppComponent,  
    PersonComponent  
  ],  
  imports: [  
    BrowserModule,  
    AppRoutingModule  
  ],  
  providers: [PersonService],  
  bootstrap: [AppComponent]  
})  
export class AppModule { }

person.service.ts :

import { Injectable } from '@angular/core';  
import { Subject } from 'rxjs';

@Injectable({  
  providedIn: 'root'  
})  
export class PersonService {  
  private personSource = new Subject();  
  personSource$ = this.personSource.asObservable(); 

  announcePerson(person) {  
    this.personSource.next(person);  
  }}

app.component.ts :

import { Component } from '@angular/core';  
import { PersonService } from './person.service';

@Component({  
  selector: 'app-root',  
  templateUrl: './app.component.html',  
  styleUrls: ['./app.component.css']  
})  
export class AppComponent {  
  person = {}; constructor(private personService: PersonService) {  
    personService.personSource$.subscribe(  
      person => {  
        this.person = person;  
      });  
  }  
}

app.component.html :

<app-person></app-person>  
<p>{{person.name}}</p>

person.component.ts :

import { Component } from '@angular/core';  
import { PersonService } from '../person.service';

@Component({  
  selector: 'app-person',  
  templateUrl: './person.component.html',  
  styleUrls: ['./person.component.css']  
})  
export class PersonComponent {  
  constructor(private personService: PersonService) { } 

  setPerson() {  
    this.personService.announcePerson({ name: 'Jane' });  
  }  
}

person.component.html :

<button (click)='setPerson()'>Set Person</button>

In the code above, we have the PersonService , whre we created a new Subject and converted it to an Observable.

In the annoucePerson method, we take in a person object and call next on personSource to broadcast the person object via the personSource$ Observable.

Then in AppComponent , we subscribe to the personSource$ Observable by writing:

personService.personSource$.subscribe(  
      person => {  
        this.person = person;  
      });

to get the latest value of person from the Observable.

In person.component.html , we added a button as follows:

<button (click)='setPerson()'>Set Person</button>

When we click it, we call the setPerson method, which calls the annoucePerson method from the PersonService we have above with the object that we wanted to pass in.

Since AppComponent subscribed to the personSource$ Observable, we should get the latest value of person.name .

Therefore, when we click Set Person, we should get ‘Jane’ displayed on the screen.

Conclusion

We can communicate between parent and child components in many ways.

We can add a template variable on the child component in the parent template and then access its public members on the parent template.

To access a child component’s members in the parent component, we can do it via the ViewChild which references the child component in the parent component.

Lastly, we can create a service that’s shared between the parent and child component, and then called the Subject ‘s next method to broadcast the message via the Observable.

Then the parent subscribes to the Observable and gets the latest value broadcasted from there.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *