From component to @component in Angular

Article contents include:

  • Component architecture
  • Stateful / stateless components
  • One-way dataflow
  • Lifecycle hooks

What is a Component?

gif1.gif

A component is created from a template and controller which explicitly couple the markup and logic as a single cohesive unit. It acts as an isolated piece of behavior or functionality that allows us to divide behavior into roles. The component is used as a logical building block for any application.

Example: Chat Application

download.png

Component Property Bindings

We have an app component which simply renders out this chat element. This chat element can be an entire view or entire component which was made up of different components. It could be a completely new view on its own. It could be a rooted component, past data, but we are hard coding for the page like below.

<div>

                <chat></chat>

</div>

Inside this chat element, we have a base element and we create a component, generate a selector and add a template URL. Now the life cycle hook actually tie into particular phases of the component life cycle. The component manages all the data for the specific roles even if we have different components which are being driven from the container.

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

import {ChatService } from '../chat.service';

@Component({

                selector: 'chat',

                templateUrl: './chat.component.html'

})

export cass ChatComponent implements OnInit
{
profile: any;
chats: Object[];
constructor(private chatService: ChatService) {}
ngOnInit()
{
let response: any = this.chatService.getChatStuff();
this.profile = response.profile;
this.chats = response.chats;
}

Stateful and Stateless Components

When something is stateful, it is actually storing information in the component's state which is a central point. It has the ability to be updated. In a stateless component, the internal state is calculated, but never directly mutates. For this purpose, a complete referential transparency is required to produce the same output. The stateful components are the one that manage child components. Following is the template for the stateful components.

<chat-profile

                [profile]="profile">

</chat-profile>

 

<chat-filter

                [status]="profile"

                (filter)="handleFilter($event);">

</chat-filter>



<chat-list

                [chats]="chats"

                (select)="handleUserUpdate($event);">

</chat-list>

The classes in the below code are stateless as they don't fetch state and data, but we pass data in it and they are updated. There are three elements in the chat filter which allow us to change the stateless. We also have the chat list. For the stateful component, it has the data and passes it down. Inside the chat list, we have an input and an output. The input is the data and the output is the manipulated data or something we want to tell the parent. In the below code, chats is an input and select is an output.

export class ChatListComponent {

                constructor() { }

                @Input() chats;

                @Output() select: EventEmitter<any> = new EventEmitter();

                onUserUpdate({ updatedUser }) {

                this.select.emit({ updatedUser });

}

We can expect an event object back which will pass it back up to the parent component. If any user will edit name, that change will communicate with a service all in one place. We are not managing different components. In this case, we actually go inside the chat list to use the repeats just for rendering dominoes. For this operation, we are using Li and just simply print out a list. Now we are using a component inside that list and just pass the details of this particular chat.

<ul>

                <li

                *ngFor="let chat of chats;">

                <chat-conversation

                [chat]="chat"

                (update)="onUserUpdate($event);">

                </chat-conversation>

                </li>

</ul>

If we go through that code, we know that the chat is an input and an update is an output. At this moment, there are three levels. The high level container which is the chat, the chat list and then the chat conversion. If there is any update in the chat conversation, there is no need to communicate with the service because the parents will not know about it or other components might also don't know about it, and managing state becomes more difficult.

@Component ({

                selector: 'chat-conversation''

                templateUrl: './chat-conversation.component.html'

})

 

export class ChatConversationComponent {

@Input() chat: Object;

@Output() update: EventEmitter<any> = new EventEmitter();

// ngOnChanges(changes) {

// if (changes.chat) {

// this.chat = Object.assign({}, changes.chat.currentValue();

}

To cope with this problem, we create an event and when something changes, we just call the below update and omit an event up.

updateUsername() {

                this.update.emit({

                updateUser: this.chat

});

We have the container components and they are stateless components because none of them are taking any data. If there is a pure JavaScript function, we have an input and with same input, it would give the same output. In such case, the input is a function itself. Inside that function, we can mutate the data or whatever the function is actually doing. Once, it is ready, we can use a return statement and just return data from the function. It can be only done in Angular 2 app and two-way binding is sometimes unpredictable. In the below code, NG changes before it is mounted and it will sync the data and the bindings. This chat is an expected input which will be bound and this is how the component is mounted.

@Input()chat: Object;

It runs like before the component is ready which means we can actually do something beforehand. The code depicts that a new object is created and bind it to this.chat. The web pack is not broken in this case and the parent is not updated. The object is completely managed and self-contained. We can change the object when we are willing to and we can tell the parent.

download2.PNG
download3.PNG

In AngularJS, we are using the controller as name space for this purpose, we are adding control and update the code. The bindings are same in both Angular version. We have an input and use the above syntax. For an output, there is a function passed in.

download4.PNG

Conclusion

The discussion covers the following:

1- Angular component concepts

2- Communicating to AngularJS 2 components

3- The input and output in AngularJS and 2

4- Difference in the code of AngularJS and 2

5- Stateless and Stateful components