Angular: In and Outs

Angular: In and Outs

·

3 min read

In this article, I am going to cover communication between components via inputs, outputs and event emitters.

Output should be used to send/receive data between a child and parent component. Input is leveraged to receive data from a parent component, and Output is leveraged to send data to the parent component.

Parent to Child Communication: Input

When dealing with a situation where the parent component needs to pass data to a child component, use the Input property. The Input property is the base level communication from a parent component to a child component.

Below is an example child component with a text input property.


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

@Component({
  selector: 'app-child',
  template: `
    <h3>Hello, {{ text }}</h3>
  `
})
export class AppChildComponent {
  @Input()
  text = '';
}

In the above example, a text Input property is declared and set to an empty string. The value can be changed within the child component or within the parent component.


<app-child text="Ryan"></app-child>

Input properties can be intercepted with a setter, or within ngOnChanges, in order to perform manipulation on the value. In the below example, we take the text Input property and add an exclamation point to the string.


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

@Component({
  selector: 'app-child',
  template: `
    <h3>Hello, {{ text }}</h3>
  `
})
export class AppChildComponent {
  @Input()
  get text() {
    return this._text;
  }
  set text(val: string) {
    this._text = val ? `${val.trim()}!`: 'World!';
  }

  private _text = '';
}

In the below example, we do the exact same operation as the above example, but leverage ngOnChanges.


import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';

@Component({
  selector: 'app-child',
  template: `
    <h3>Hello, {{ text }}</h3>
  `
})
export class AppChildComponent {
  @Input()
  text = '';

  ngOnChanges(changes: SimpleChanges) {
    if(changes.text) {
      if(this.text) {
        this.text = this.text ? `${this.text.trim()}!`: 'World!';
      }
    }
  }
}

Both examples perform the same functionality, but do it in different ways. Some developers prefer to leverage ngOnChanges when interacting with multiple Input properties.

Child to Parent Communication: Output

When dealing with a situation where the child component needs to pass data to the parent component, use the Output property. The Output property is the base level communication from a child component to the parent component. The Output property is generally used in situations where the child component needs to trigger a method on a parent component.

A good example would be when the child component has a button on it that the parent component will perform an action when clicked.


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

@Component({
  selector: 'app-child',
  template: `
  <button type="button" (click)="_onButtonClick()">Test</button>
  `
})
export class AppChildComponent {
  @Output()
  buttonClick = new EventEmitter<string>();

  _onButtonClick() {
    this.buttonClick.emit('test button click value');
  }
}

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

@Component({
  selector: 'app-child',
  template: `
  <app-child (buttonClick)="_onChildButtonClick($event)"></app-child>
  `
})
export class AppChildComponent {
  _onChildButtonClick(childValue: string) {
    console.log(`Child component emitted ${childValue}`);
  }
}