Introduction to Angular Component

Published Dec 05, 2017Last updated Dec 13, 2017

Components: Basic Idea

Components are the most basic building block of a UI in an Angular application. They are directives with special decorator (@Component) and template. Component decorator allows you to mark a class as an Angular component and provide additional metadata that determines how the component should be processed, instantiated and used at runtime. Below is an example of a component:

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

@Component({ 
    selector: 'hello-component', 
    templateUrl: './hello-component.html', 
    styleUrls: ['./hello-component.css']
}) 
class Greet { 
    public name: string = 'Component'; 
}

This component can be used any where in the template like this <hello-component></hello-component>. The templateUrl specify the part to the component’s template, the styleUrls specify the part to the component’s style, the public variable name is use to pass a parameter to the component’s template which can be accessed using {{ name}} in the template.

Component lifecycle hooks

Components can control their runtime behaviour by implementing various Life-Cycle hooks. Component instances have a lifecycle as Angular creates, updates, and destroys them. Developers can tap into key moments in that lifecycle by implementing one or more of the lifecycle hook interfaces in the Angular core library. There are eight main hooks for every component to have robustness in our built applications, the diagram below arranged them in order of execution.


reference http://www.techjini.com/blog/angular2-lifecycle-hooks/ for the image

There are many component’s lifecycle hooks but I will only talk about those I feel important to talk about in this article due to their usage. You can visit angular to read more about angular life cycle hook.

constructor: The constructor is not a part of the angular component life cycle hook but constructor is predefined default method of the typescript class. The constructoris called before any other component lifecycle. Normally it’s best practice to not do anything in the constructor and just use it for classes that will be injected. Most of the time your constructor should look like this:

constructor(private http: Http, private service: CustomService) {}

ngOnInit: The ngOnInitmethod of a component is called directly after the constructor and after the ngOnChange is triggered for the first time. You should use ngOnInit if the initialisation processing of your function relies on bindings of the component (for example component parameters defined with @Input)

Components Relationship

Angular is built up of many components. There is a root component that serves as the parent component, every other components can be called a Child Component to the root component since the root component is the Parent Component. Assuming there is a root component that houses two Child Components (component-a and component-b). We can simply say component-a and component-b are sibling components.


reference https://angularfirebase.com/lessons/sharing-data-between-angular-components-four-methods/

Sharing data between Components

To share data between components, we have to define the kind of relationship that exists between the components. Is it a Parent to Child relationship or a Sibling relationship? The kind of relationship will determine the best way to share data between the components.

Parent to child: share data via @Input decorator: The easiest way to pass data from parent to child is to use the @Input binding which allows data to be shared via the template like below:

//parent.component.ts


import { Component } from '@angular/core';import { ChildComponent } from './child.component';


@Component({ 
    selector: 'parent-component', 
    template: ` <child-component [messageToChild]="parentMessage"> 
        </child-component> 
    `, 
    styleUrls: ['./parent.component.css']
})
export class ParentComponent { 
    parentMessage = "message from parent"; 
    constructor() {};
}

The @Input decorator is used by the child component to accept data coming from a parent. The [childMessage] in the parent component is the same name as the property in the child component.

//child.component.ts

import { Component } from '@angular/core';import { ParentComponent } from './parent.component';

@Component({ 
    selector: 'child-component', 
    template: ` {{ childMessage }} `, 
    styleUrls: ['./parent.component.css']
})
export class ChildComponent { 
    @Input() childMessage: string; 
    constructor() {};
}

Child to parent: share data via @Output Decorator and EventEmitter: The @Output decorator is used to emit data(events) out of a component to a parent component.


import { Component, Output, EventEmitter } from '@angular/core';import { ChildComponent } from './child.component';


@Component({ 
    selector: 'child-component', 
    template: ` 
     <button (click)="sendMessageToParent()"> 
        Send Message To Parent         
     </button> 
    `, 
    styleUrls: ['./child.component.css']
})
class ChildComponent { 
    @Output() messageFromChild = new EventEmitter(); 
    sendMessageToParent() { 
        this.messageFromChild.emit('Message from child'); 
    }
}

The parent is listening and passes a callback to do appropriate action when the data (event) is received.

@Component({ 
    selector: 'parent-component', 
    template: ` <child-component (messageFromChild)="onMessageRecieved($event)">     
      </child-component> 
    `, 
    styleUrls: ['./parent.component.css']
})
class ParentComponent { 
    onMessageRecieved(event) { 
        console.log(event); 
    }
}

Parent to child: share data via ViewChild: ViewChild makes it easy to access a child component methods or access instance variables that are available on the child’s component. Let’s say we have a child component with a childMethod method like this:

childMethod() { 
    //a method inside child component
}

We can then call that method from within our parent component class with ViewChild like this

import {Component, ViewChild, AfterViewInit} from "@angular/core";import { ChildComponent } from './child.component';


@Component({ 
    selector: 'parent-component', 
    template: ` Message From Child Component: {{ message }} 
    `, 
    styleUrls: ['./parent.component.css']
})
class ParentComponent { 
    @ViewChild(ChildComponent) childComponent: ChildComponent; 
    public message: any;

    ngAfterViewInit() { 
        this.childComponent.childMethod(); // 👶 I am a child method! 
    }
}

One caveat, however, is that child won’t be available until after the view has been initialized. This means we need to implement the AfterViewInit lifecycle hook to receive the data from the child like the above.

Siblings(directly unrelated components): via Service classes: To share data between components that lack a direct connection, such as siblings, grandchildren, etc, you should use a service. Here is a sample service below:

//data.service.ts

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

@Injectable()
export class DataService {
}

The data could be any type, including object. And there could be more code inside the service, such as code to retrieve default values or values to be shared. Each component then injects this service and uses it value.

//componentA.component.ts

import { Component } from '@angular/core';import { DataService } from './data.service';

@Component({
 ... ...
})
export Class ComponentA { 
    constructor(public dataService: DataService) {}
    get data():string { 
        return this.dataService.serviceData(); 
    }

    set data(value: string) { 
        this.dataService.setDate = value; 
    }
}

//componentB.component.ts
import { Component } from '@angular/core';
import { DataService } from './data.service';


@Component({
    ...
    ...
})
export class ComponentB {
    constructor(public dataService: DataService){}

    get data(): string {
        return this.dataService.serviceData();
    }

    set data(value: string) {
        this.dataService.setData = value;
    } 
}


With this article on angular components, I have tried to cover what I feel are the most important things to get started with angular components. Please reach out to me if you have any suggestions or if you think I have missed something

For more musing about programming, please follow me here or on twitter

Discover and read more posts from Abel AGOI
get started