Skip to content

Instantly share code, notes, and snippets.

@ReeMii
Last active January 15, 2022 15:23
Show Gist options
  • Save ReeMii/a34e5caa6a772b2d8339df211d1feb07 to your computer and use it in GitHub Desktop.
Save ReeMii/a34e5caa6a772b2d8339df211d1feb07 to your computer and use it in GitHub Desktop.
communications patterns in angular #angular

Angular follows a two-way data flow pattern, meaning you can send data up and down the component tree.

Everything in the Angular is a component.

Component basics

Interpolation

Interpolation is the way to inject some value into HTML. We are injecting title from the component class to the HTML.

<h1>
 Welcome to {{ title }}!
</h1>

Property Binding

Property Binding is used to send the information from the component class to view with the square brackets [].

<app-header [title]="title"></app-header>

Event Binding

Event Binding is used to send the information from the view class to component class with the normal brackets ().

<app-header (click)="updateHeader()"></app-header>

Parent to child communication

We have @Input() headerTitle in the header and we use property binding [headerTitle] in the app component to pass the title.

<app-header [headerTitle]="title"></app-header>
import { Component, OnInit, Input } from '@angular/core';

@Component({
  selector: 'app-header',
  templateUrl: './header.component.html',
  styleUrls: ['./header.component.css']
})
export class HeaderComponent implements OnInit {

  constructor() { }

  @Input() headerTitle: string;

  ngOnInit() {
  }

}

Child to Parent Communication

We have @Output decorator and EventEmitter to send the information from the child component to the parent component.

// header.component.ts

import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'app-header',
  templateUrl: './header.component.html',
  styleUrls: ['./header.component.css']
})
export class HeaderComponent implements OnInit {

  constructor() { }

  @Input() headerTitle: string;
  @Output() navOut = new EventEmitter();

  onNavLink(linkName: string) {
     this.navOut.emit(linkName);
  }

  ngOnInit() {
  }

}

When the event is emitted, it will be captured here in the app component as shown below. We define onNavigation() method in the app component to capture the emitted value and assign that to linkName property. We can place this linkName property in the HTML file with an interpolation {{linkName}}.

// app.component.html

<app-header
    [headerTitle]="title"
    (navOut)="onNavigation($event)"
  >
</app-header>
//app.component.ts

export class AppComponent {
  title = 'angular-communication';
  linkName: string;

  onNavigation(navLink: string) {
    this.linkName = navLink;
  }
}

Sibling communication with services

Define Subject in the services which receives the data from the Header component. Footer component subscribes to the Subject defined in the services and receives data as soon as data is emitted by Subject with the next function.

// app.service.ts

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

@Injectable({
  providedIn: 'root'
})
export class AppService {

  constructor() { }

  public isUserLoggedIn = new Subject();

  setUserLoggedIn(loggedIn: boolean) {
    this.isUserLoggedIn.next(loggedIn);
  }
}
// footer.component.ts

export class FooterComponent implements OnInit {

  constructor(private appService: AppService) { }
  isUserLoggedIn: boolean;

  ngOnInit() {
    this.appService.isUserLoggedIn.subscribe((userLoggedIn: boolean) => {
        this.isUserLoggedIn = userLoggedIn;
    });
  }

}
// header.component.ts

export class HeaderComponent implements OnInit {

  constructor(private appService: AppService) { }

  loginLabel = 'login';

  onNavLink(linkName: string) {
    if (linkName === 'logout') {
      this.loginLabel = 'login';
      this.appService.setUserLoggedIn(false);
    } else if (linkName === 'login') {
      this.loginLabel = 'logout';
      this.appService.setUserLoggedIn(true);
    }
    this.navOut.emit(linkName);
  }
}

Sibling communication with EventEmitter

<!-- app.component.html -->

<!--The content below is only a placeholder and can be replaced.-->
<div style="text-align:center">
  <app-header
    [headerTitle]="title"
    (navOut)="onNavigation($event)"
    (setLoggedInFlag)="setLoggedInUser($event)"
  >
  </app-header>
  
  <app-footer
    [isUserLoggedIn]="loginFlag"
  >
  </app-footer>
</div>
// app.component.ts

// removed for brevity
export class AppComponent {
  title = 'angular-communication';
  linkName: string;

  loginFlag: boolean;

  setLoggedInUser(loggedIn: boolean) {
    this.loginFlag = loggedIn;
  }
}
// footer.component.ts

// removed for brevity
export class FooterComponent implements OnInit {

   constructor() { }
   _isUserLoggedIn: boolean;

   get isUserLoggedIn(): boolean {
      return this._isUserLoggedIn;
   }

  @Input()
  set isUserLoggedIn(value: boolean) {
      this._isUserLoggedIn = value;
  }

}

Communication using @ViewChild decorator

@ViewChild is one of the common decorators we use in Angular. With this we can obtain the reference of the custom angular component by querying the template.

// app.ts 

// parent html

<div class="parent">
  <h2>I am a Parent</h2>
  <app-child #child></app-child>
</div>

// parent component class. removed everything for brevity

export class ParentComponent implements OnInit, AfterViewInit {

  constructor() { }

  @ViewChild('child') childComp: ChildComponent;

  ngAfterViewInit() {
    this.childComp.title = 'title coming from parent';
  }
}
// child.ts

// child html
<div>
  <h4>{{title}}</h4>
</div>

// child component class

export class ChildComponent implements OnInit {

  constructor() { }
  title = 'I am a child';

  ngOnInit() {
  }
}

Communication using content projection

<app-welcome-message>
  <h2>Welcome to APP!</h2>
</app-welcome-message>
<!-- app-weelcome-message -->

<div>
  <ng-content></ng-content>
</div>

Communication with NGRX store

NGRX is a state management tool inspired by redux for the Angular Applications.

Communication between modules

NGRX Store

Shared module

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment