Introduction
Today, we’ll learn how to use reusable components in Angular. So here, we’ll see how to pass the data from component to Views and we’ll raise the custom events. We’ll apply the styles to the HTML elements in the template.
- Introduction And Setting Up The Environment - Part One
- Typescript In a Nutshell - Part Two
- Building Blocks of Angular - Part Three
- Binding Variations And Displaying Data - Part Four
In this article, we’ll cover
- Component API
- Input Properties
- Aliasing Input Properties
- Output Properties
- Passing Event Data
- Aliasing Output Properties
- Templates
- Styles
- View Encapsulation
- Shadow DOM
- ngContent
- ngContainer
- What we have learned
- Conclusion
Component API
In the last article, we’ve learned property and event binding.
Property Binding (Square Bracket Syntax):
- <img [src]=”imageUrl” />
It is used to bind the DOM objects to fields or properties in a host component. Here is the component that is using DOM objects; in this case, img object.
Another way of thinking about this statement is that this src property is an input into this DOM object. We use this to supply data to this object, supply some state.
Similarly, we use event binding respond to the events raised from the DOM object.
- <button (click)=”onClick()”></button>
In this case, the click event of the button. But the star component we implemented in the last article doesn’t have any property and event binding.
<star></star>It isn’t reusable. Ideally, I want to set the initial state of this star component using some object that we have in the host component. Here, in the app component, let’s say we get the post object from the server.
- @Component({
- selector: 'app-root',
- templateUrl: './app.component.html',
- styleUrls: ['./app.component.css']
- })
- export class AppComponent {
- post = {
- title: "Title",
- isFavorite: true
- }
- }
Input Properties
So, here in the star component, we want to mark the isFavorite field as an input property. So we can use it in property binding expression. And now, there are 2 ways to mark this field as an input property.
- <star [isFavorite]="post.isFavorite"></star>
Here, unfortunately, we can’t use property binding to bind isFavorite field of star component to the post object. This is not going to work. Now just open your browser and here we’ll see this error.

- <star [isFavorite]="post.isFavorite" (click)="onClick()"></star>
And inside that method, we can call the server or do something else. Once again, we need to add support for event binding as well. We need to define the special property in star component that can be referred to as output property.
In other words, in order to make a component more reusable, we need to add a bunch of input and output properties. We use input properties to pass input or state to a component and we use output property to raise events from this custom component. A combination of input and output properties for a component make up what we call Component API (public API of that component).
So now, we don’t have component API in star component because it doesn’t have any input and output properties.
Input Properties
So here in star component, we want to mark the isFavorite field as an input property. So we can use it in property binding expression. There are 2 ways to mark this field as an input property.
- import { Component, OnInit, Input } from '@angular/core';
- @Component({
- selector: 'star',
- templateUrl: './star.component.html',
- styleUrls: ['./star.component.css']
- })
- export class StarComponent implements OnInit {
- @Input() isFavorite: boolean;
- constructor() { }
- ngOnInit() {
- }
- onClick(){
- this.isFavorite = !this.isFavorite;
- }
- }
By default, it is filled because we have to bind our property with the app component post's isFavorite property and we set it to true there. So it is filled. Now our property binding works perfectly.
Now the 2nd approach is to make input property. We use Inputs property in Component declaratory.
- import { Component, OnInit } from '@angular/core';
- @Component({
- selector: 'star',
- templateUrl: './star.component.html',
- styleUrls: ['./star.component.css'],
- inputs: ['isFavorite']
- })
- export class StarComponent implements OnInit {
- isFavorite: boolean;
- constructor() { }
- ngOnInit() {
- }
- onClick(){
- this.isFavorite = !this.isFavorite;
- }
- }
- @Component({
- selector: 'star',
- templateUrl: './star.component.html',
- styleUrls: ['./star.component.css'],
- inputs: ['isFavorite']
- })
- export class StarComponent implements OnInit {
- isSelected: boolean;
- constructor() { }
- ngOnInit() {
- }
- onClick(){
- this.isSelected = !this.isSelected;
- }
- }
- <star [isFavorite]="post.isFavorite" (click)="onClick()"></star>
And the value of isFavorite in app component is true. That’s it; just in fill state, click event is not applying on it because click event is changing the state of isSelected, not isFavorite.
So that’s why it is a bad approach although it is quite clean instead of the first approach but it is not recommended. Most of the time when the language contains multiple ways to do anything then it confuses the beginners in learning. So the best approach to make the input property is by using Input declarator. So this is how we define Input properties.
Aliasing Input Properties
We’ve learned how to define the input properties, now let’s explore how to define the aliasing of input properties.
- export class StarComponent implements OnInit {
- @Input() isFavorite: boolean;
- }
- <star [is-favorite]="post.isFavorite" (click)="onClick()"></star>
Look now we’ve changed the property as is-favorite. Now in Javascript and in Typescript we don’t have this kind of acceptable identifier because we can just make the variable without dash in JS.
So the solution to this kind of problem is to use the alias or a nickname for an input property. So back in star component here we’re using Input declaratory and here we’ll supply the string for the alias of this property.- @Input('is-favorite') isFavorite: boolean;
And now if you run the application, you’ll see it is working without any issue.
This aliasing actually gives the contract of this API stable. Let’s go back to app component and revert back.
- export class StarComponent implements OnInit {
- @Input() isFavorite: boolean;
- constructor() { }
- ngOnInit() {
- }
- onClick(){
- this.isFavorite = !this.isFavorite;
- }
- }
- export class StarComponent implements OnInit {
- @Input() isSelected: boolean;
- onClick(){
- this.isSelected = !this.isSelected;
- }
- }
- @Input('isFavorite') isSelected: boolean;
- <span class="glyphicon"
- [class.glyphicon-star]="isFavorite"
- [class.glyphicon-star-empty]="!isFavorite"
- (click)="onClick()"
- ></span>
- <span class="glyphicon"
- [class.glyphicon-star]="isSelected"
- [class.glyphicon-star-empty]="!isSelected"
- (click)="onClick()"
- ></span>
Output Properties
So now we want to be notified when the user clicks on star. So here we want to raise the custom event ‘change’ and define them in the star component.- <star [isFavorite]="post.isFavorite" (change)="onStarChange()"></star>
- export class AppComponent {
- post = {
- title: "Title",
- isFavorite: true
- }
- onStarChange(){
- console.log('Star Changed');
- }
- }
Now it is the time to make the change event output property. As we use Input declarator, similar here we use @Output declaratory and we’ll initialize @Output declarator variable with EventEmitter() it actually helps us to raise and publish the events.
- import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
- @Component({
- selector: 'star',
- templateUrl: './star.component.html',
- styleUrls: ['./star.component.css']
- })
- export class StarComponent implements OnInit {
- @Input('isFavorite') isSelected: boolean;
- @Output() change = new EventEmitter();
- constructor() { }
- ngOnInit() {
- }
- onClick(){
- this.isSelected = !this.isSelected;
- this.change.emit();
- }
- }
And here is the star component code. We need to call the emit() function with click output property. Now if we run the application
Look it is working fine on star click as we’re printing the console message on Star click.
Passing Event Data
So here we’ll see how to pass event data when raising an event. Here in app component currently we’re just displaying a single message on console.- onStarChange(){
- console.log('Star Changed');
- }
Here we don’t know anything about this event. We’re just raising an event which is displaying the message on console. We even don’t know if the user has marked the object as favorite or not. So we need to change our implementation and pass some data when raising an event. So back in our star component, when we’re emitting the event we can optionally pass some value and this value will be available to all the subscribers of this event. And here in our case, change event subscriber is app component onStarChange() function.
- export class StarComponent implements OnInit {
- @Input('isFavorite') isSelected: boolean;
- @Output() change = new EventEmitter();
- constructor() { }
- ngOnInit() {
- }
- onClick(){
- this.isSelected = !this.isSelected;
- this.change.emit(this.isSelected);
- }
- }
Look here we’re passing isSelected property to change event. Now we’re consuming this star component into app component. So open app.component.ts and make some changes.
- export class AppComponent {
- post = {
- title: "Title",
- isFavorite: true
- }
- onStarChange(isFavorite){
- console.log('Star Changed ', isFavorite);
- }
- }
So we’re just catching the parameter and displaying it into console. And now open app.component.html
- <star [isFavorite]="post.isFavorite" (change)="onStarChange($event)"></star>
- onClick(){
- this.isSelected = !this.isSelected;
- this.change.emit({ newValue: this.isSelected });
- }
And now here $event object is representing a Javascript object that has the property called newValue.
- <star [isFavorite]="post.isFavorite" (change)="onStarChange($event)"></star>
- onStarChange(eventArgs){
- console.log('Star Changed ', eventArgs);
- }
You might be working in some kind of complex project and you want to show the intellisense while you’re working or you want compile time checking. So you need to apply the data annotations for the parameters.
- onStarChange(eventArgs: { newValue: boolean }){
- console.log('Star Changed ', eventArgs);
- }
Look here with the inline annotation we’ve applied the type of the parameter. But it is little bit messy. Now if you remember typescript, we’ve already discussed interfaces. With the help of interface, we can make our implementation more robust and we can make our code clean.
- import { Component } from '@angular/core';
- import { debug } from 'util';
- interface StarChangedEventArgs {
- newValue: boolean;
- }
- @Component({
- selector: 'app-root',
- templateUrl: './app.component.html',
- styleUrls: ['./app.component.css']
- })
- export class AppComponent {
- post = {
- title: "Title",
- isFavorite: true
- }
- onStarChange(eventArgs: StarChangedEventArgs){
- console.log('Star Changed ', eventArgs);
- }
- }
- import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
- @Component({
- selector: 'star',
- templateUrl: './star.component.html',
- styleUrls: ['./star.component.css']
- })
- export class StarComponent implements OnInit {
- @Input('isFavorite') isSelected: boolean;
- @Output() change = new EventEmitter();
- constructor() { }
- ngOnInit() {
- }
- onClick(){
- this.isSelected = !this.isSelected;
- this.change.emit({ newValue: this.isSelected });
- }
- }
- export interface StarChangedEventArgs {
- newValue: boolean;
- }
- import { StarChangedEventArgs } from './star/star.component';
- import { Component } from '@angular/core';
- import { debug } from 'util';
- @Component({
- selector: 'app-root',
- templateUrl: './app.component.html',
- styleUrls: ['./app.component.css']
- })
- export class AppComponent {
- post = {
- title: "Title",
- isFavorite: true
- }
- onStarChange(eventArgs: StarChangedEventArgs){
- console.log('Star Changed ', eventArgs);
- }
- }
To resolve the reference file issue, auto import extension helps us a lot really. And on the opposite side our application is working fine.
Aliasing Output Properties
So earlier we’ve learned how we can use an alias to keep the contract of the component stable. Previously we’ve used an alias for an input property but we can also use an alias on an output property.
- export class StarComponent implements OnInit {
- @Input('isFavorite') isSelected: boolean;
- @Output() change = new EventEmitter();
- constructor() { }
- ngOnInit() {
- }
- onClick(){
- this.isSelected = !this.isSelected;
- this.change.emit({ newValue: this.isSelected });
- }
- }
So here, tomorrow if we decide to change the name of this event from change to something else our application will certainly break or might not work properly. Let’s take an experiment.
- export class StarComponent implements OnInit {
- @Input('isFavorite') isSelected: boolean;
- @Output() click = new EventEmitter();
- constructor() { }
- ngOnInit() {
- }
- onClick(){
- this.isSelected = !this.isSelected;
- this.click.emit({ newValue: this.isSelected });
- }
- }
Now look, the subscriber of Star component is still expecting a change event.
- <star [isFavorite]="post.isFavorite" (change)="onStarChange($event)"></star>
And if you run the application, our component is working properly but doesn’t show the log messages in the console which we’re displaying through onStarChange() event of Star component.
Now you might be thinking that app.component.html contains change event which doesn’t exist then why isn't our application broken. It is because our app component is expecting that it may exist sometimes in the future that’s why it doesn’t give us any error in the browser. But the code actually is broken because event handler onStarChange() is not called. So always it is the better choice to use alias to make sure if in the future we rename this field, the subscriber of the component is not going to break. So,
- export class StarComponent implements OnInit {
- @Input('isFavorite') isSelected: boolean;
- @Output('change') click = new EventEmitter();
- constructor() { }
- ngOnInit() {
- }
- onClick(){
- this.isSelected = !this.isSelected;
- this.click.emit({ newValue: this.isSelected });
- }
- }
And now if we run the application, we’ll see it is working fine. And our onStarChange() method is logging the message in console.
Templates
We’ve seen 2 forms of using template. One way is to use the template externally and then we use the templateUrl property of component metadata to specify the path to the template file and another approach is to use template property. So we can add the template inline here. Now please don’t mix these approaches, you can follow only 1 approach.
- @Component({
- selector: 'star',
- templateUrl: './star.component.html',
- template: '',
- styleUrls: ['./star.component.css']
- })
Now you might ask which approach is better.
It really depends, if you’re building a small component with a very simple template we can add the template here in the component declarator which would be easy to work with and to import it into multiple applications. Yes you can use your component into multiple applications. Just copy your component folder and paste it into any application where you want and just use it like we do here in app component. If your template is more than 5 lines of code, you can think your own that this code is quite busy and too noisy. So in that case the best approach is to store it in the external file.
Now you might think that as it is a separate file so there will be a new request for template files. Actually that’s not the case here. Remove the redundant template.
- @Component({
- selector: 'star',
- templateUrl: './star.component.html',
- styleUrls: ['./star.component.css']
- })
Open your app.component.html and place a heading here with any name.
- <h2>Usama Shahid</h2>
- <star [isFavorite]="post.isFavorite" (change)="onStarChange($event)"></star>

Look all of our external templates are actually bundled along with our javascript code. So there is no separate request to the server to download the template files.
Styles
As we build components, sometimes we need to apply styles on the components. In Angular there are 3 ways to apply styles to a component but first of all let’s remove the unnecessary code.- export class StarComponent {
- @Input('isFavorite') isSelected: boolean;
- @Output('change') click = new EventEmitter();
- onClick(){
- this.isSelected = !this.isSelected;
- this.click.emit({ newValue: this.isSelected });
- }
- }
We’ll see OnInt interfaces later, at the moment we don’t need it. So there are 3 ways to apply styles.
- @Component({
- selector: 'star',
- templateUrl: './star.component.html',
- styleUrls: ['./star.component.css']
- })
- @Component({
- selector: 'star',
- templateUrl: './star.component.html',
- styleUrls: ['./star.component.css'],
- styles: [
- `
- `
- ]
- })
And the third way to apply the styles is by writing it in our html template. However it is not the good approach but angular allows you to follow this approach. Now it is up to you what you prefer.Now you might want to ask why we put array syntax here, why not just a simple string. Honestly I don’t know the reason of this design. If you know then comment here and let me know as well.
And the interesting thing is Angular doesn’t limit you to use only 1 option among both of them, you can use styleUrls and styles as well. Last style will affect the html element in the browser.
- <style>
- </style>
- <star [isFavorite]="post.isFavorite" (change)="onStarChange($event)"></star>
So let’s see how the styles are overriding each other. So first of all let’s open the external stylesheet and apply the styles here.
And now open star component and apply the style in component declaratory
- @Component({
- selector: 'star',
- templateUrl: './star.component.html',
- styleUrls: ['./star.component.css'],
- styles: [
- `
- .glyphicon {
- color: green;
- }
- `
- ]
- })
Now when we run the application, our icon will be green because we apply this last.

However if we change the arrangement of reference style files,
- @Component({
- selector: 'star',
- templateUrl: './star.component.html',
- styles: [
- `
- .glyphicon {
- color: green;
- }
- `
- ],
- styleUrls: ['./star.component.css']
- })
Then obviously our icon becomes red. Because external style file css comes in last.

- @Component({
- selector: 'star',
- templateUrl: './star.component.html',
- styles: [
- `
- .glyphicon {
- color: green;
- }
- .glyphicon-star {
- background: black;
- }
- `
- ],
- styleUrls: ['./star.component.css']
- })
Look here we define glyphicon and glyphicon-star and we’re just overriding glyphicon class in external stylesheet. So our result should be star with red color and black background color.
- <style>
- .glyphicon {
- color: blue;
- }
- </style>
- <span class="glyphicon"
- [class.glyphicon-star]="isSelected"
- [class.glyphicon-star-empty]="!isSelected"
- (click)="onClick()"
- ></span>
And here is the star.component.html code. Now if we run the application

Here we see blue color star.
Now irrespective of which approach you choose, what is interesting in Angular is that you can create the scope of these styles so that these styles can’t leak outside of these component templates. So if you’ve glyphicon somewhere else in the html document.- @Component({
- selector: 'star',
- templateUrl: './star.component.html',
- styles: [
- `
- .glyphicon {
- color: green;
- }
- .glyphicon-star {
- background: black;
- }
- `
- ],
- styleUrls: ['./star.component.css']
- })
These styles will not be applied to these glyphicons.
View Encapsulation
So we’ve seen that the styles we’ve applied in Components are just scoped to this component but also how it works.
So here we need the concept of Shadow DOM. It’s basically a specification that enables DOM tree and style encapsulation.
Shadow DOM allows us to apply scoped styles to elements without bleeding out to the outer world. This is the new feature in browsers but not in old browsers. It is only supported in Safari 10 or higher and Chrome 53 or higher. Let’s see shadow DOM in action. Look at this piece of code here
- var el = document.querySelector('star');
- el.innerHTML = `
- <style> h1 { color: red } </style>
- <h1>Usama</h1>
- `;
It’s the plain javascript code. Here we’re getting star element and applying the innerHtml which has style of h1 and h1 element inside.
Now the problem with this implementation is that this style leaks outside this element. So if we’ve another h1 somewhere else, it’s going to be red as well. And we don’t want that. We’re building components, and we’re going o apply some styles to this component only. Let’s say you want to use a component built by someone else, it might have defined some styles of those components and you bring that component into your application. And you don’t want those styles to override in your application that’s where Shadow DOM comes into play. We can change this code and use Shadow DOM with only 1 extra line of code.- var el = document.querySelector('star');
- var root = el.createShadowRoot();
- root.innerHTML = `
- <style> h1 { color: red } </style>
- <h1>Usama</h1>
- `;
So this is the Shadow DOM. Now you might think what does it do in Angular.
Here we’ve this concept called View Encapsulation- import { Component, OnInit, Input, Output, EventEmitter, ViewEncapsulation } from '@angular/core';
- @Component({
- selector: 'star',
- templateUrl: './star.component.html',
- styleUrls: ['./star.component.css'],
- encapsulation: ViewEncapsulation.Emulated
- })
- encapsulation: ViewEncapsulation.Emulated
- <star [isFavorite]="post.isFavorite" (change)="onStarChange($event)"></star>
- <span class="glyphicon glyphicon-user"></span>
Look here in head section we’ve 4 styles.
- 1st style is for bootstrap css
- 2nd style is for global styles which we apply in style.css in our project.
- 3rd style is for external files styles.
- 4th style is which we apply in its own component html file.
But if you ook at things closely, Angular has attached attributes with the elements [_ngcontent-c1] and with these attributes style colors are set. And if you go down here you can see 2 spans with different attribute values. The css which you’ve applied in component and its selector has same attribute name but the span which I created manually in app.component.html has different attribute name however both spans have same class glyphicon and we’re applying css on the basis of glyphicon class but it is just working with the firrst span glyphicon and not working with the second glyphicon.
So when the attribute name and class name matches then the style will be applied on that specific element. And this is the Emulated View Encapsulation which is the default View Encapsulation mode. So Angular tries to emulate the concept of shadow DOM.
- encapsulation: ViewEncapsulation.Native
Now the second value is Native. And with this instead of generating the attributes on elements dynamically, Angular uses the native Shadow DOM feature in the browser. And of course, it is not yet supported in all of the browsers right now. Let’s see how it works

Look here we’ve just 2 styles above in head section and 2 below above the span.glyphicon-star. Now it doesn’t have additional attributes.
If you can’t see the Shadow DOM here, press F1 in Elements or Console tab of your chrome in Developer tools. And make sure you’ve selected this option

Now look it doesn’t have additional attributes.
Why did our icon disappear? Because the only styles that apply to this element is the red and blue color. So none of the styles defined in bootstrap are applied to this element that’s why we don’t see the actual icon. Now if you really bring bootstrap stuff here, so just copy the bootstrap import statement from global style.css and paste it in star component css as well.
And now our blue icon is showing there.

And here above to the glyphicon-star, complete bootstrap styles are loaded and its custom style is also there. And this approach creates the performance problem as well. So it is not the recommended approach.
So go back here and remove the bootstrap import statement from component css file.- encapsulation: ViewEncapsulation.None
And now this statement means that we don’t have any need of ViewEncapsulation here. So the styles defined here will leak outside this template which means that the style will be applied on all the elements.

- @Component({
- selector: 'star',
- templateUrl: './star.component.html',
- styleUrls: ['./star.component.css'],
- })
ngContent
Imagine we want to build bootstrap panel component. So let’s create a new component called PanelComponent- PS C:\Users\Ami Jan\HelloWorld\MyFirstAngularProject> ng g c Panel
- import { Component } from '@angular/core';
- @Component({
- selector: 'bootstrap-panel',
- templateUrl: './panel.component.html',
- styleUrls: ['./panel.component.css']
- })
- export class PanelComponent {
- constructor() {}
- }
If you’re building ra eusable component then always prefix it with any word. Like here we do and prefix the selector with bootstrap. Now let’s go to the template of this panel.
Now here we use Zen Coding feature, look- div.panel.panel-default>div.panel-heading+div.panel-body
- <div class="panel panel-default">
- <div class="panel-heading"></div>
- <div class="panel-body"></div>
- </div>
This is the generated markup code. Let’s put some labels here
- <div class="panel panel-default">
- <div class="panel-heading">Heading</div>
- <div class="panel-body">Body</div>
- </div>
- <bootstrap-panel></bootstrap-panel>
And you’ll see the results in the browser.

- <div class="panel panel-default">
- <div class="panel-heading"></div>
- <div class="panel-body"></div>
- </div>
And now open app.component.html
So in order to set the Heading and Body, 1 way is to use the Property Binding. So we can define the input properties- <bootstrap-panel [heading]="heading"></bootstrap-panel>
- <div class="panel panel-default">
- <div class="panel-heading">
- <ng-content></ng-content>
- </div>
- <div class="panel-body">
- <ng-content></ng-content>
- </div>
- </div>
- <div class="panel panel-default">
- <div class="panel-heading">
- <ng-content select=".heading"></ng-content>
- </div>
- <div class="panel-body">
- <ng-content select=".body"></ng-content>
- </div>
- </div>
- <bootstrap-panel>
- <div class="heading">Heading</div>
- <div class="body">Body</div>
- </bootstrap-panel>
- <bootstrap-panel>
- <div class="heading">Heading</div>
- <div class="body">
- <h2>Body</h2>
- <p>Hello, World!</p>
- </div>
- </bootstrap-panel>
Now let’s preview this in the browser.
So in this way we can provide custom content and reusable component.
ngContainer
Now let’s inspect the heading element.
- <div class="panel panel-default">
- <div class="panel-heading">
- <ng-content select=".heading"></ng-content>
- </div>
- <div class="panel-body">
- <ng-content select=".body"></ng-content>
- </div>
- </div>
- <div class="panel panel-default">
- <div class="panel-heading">
- <div class="heading">Heading</div>
- </div>
- <div class="panel-body">
- <ng-content select=".body"></ng-content>
- </div>
- </div>
- <div class="panel panel-default">
- <div class="panel-heading">
- Heading
- </div>
- <div class="panel-body">
- <ng-content select=".body"></ng-content>
- </div>
- </div>
- <div class="panel panel-default">
- <div class="panel-heading">
- <ng-content select=".heading"></ng-content>
- </div>
- <div class="panel-body">
- <ng-content select=".body"></ng-content>
- </div>
- </div>
- <bootstrap-panel>
- <ng-container class="heading">Heading</ng-container>
- <div class="body">
- <h2>Body</h2>
- <p>Hello, World!</p>
- </div>
- </bootstrap-panel>
Look now we don’t have additional markup, we’ve just label.
What We’ve Learned
So here we’ll build the twitter like feature. A heart symbol with number of likes and changing color of heart on clicking. So let’s get started.
First of all let’s make a component.
- PS C:\Users\Ami Jan\HelloWorld\MyFirstAngularProject> ng g c like
Now let’s go to like.component.html. And here we want heart icon. So,
- <span
- class="glyphicon glyphicon-heart"
- [class.highlighted]="isActive"
- (click)="onClick()">
- </span>
- <span>{{ totalLikes }}</span>
And if we run the application here is the output.

- .glyphicon {
- color: #ccc;
- cursor: pointer;
- }
- .highlighted {
- color: deeppink;
- }
Now come back to like.component.ts
- import { Component, Input } from '@angular/core';
- @Component({
- selector: 'like',
- templateUrl: './like.component.html',
- styleUrls: ['./like.component.css']
- })
- export class LikeComponent {
- @Input('totalLikes') totalLikes: number;
- @Input('isActive') isActive: boolean;
- onClick() {
- this.totalLikes += (this.isActive) ? -1 : 1;
- this.isActive = !this.isActive;
- }
- }
Now go back to app.component.ts and here we need to create the tweet object.
- import { Component } from '@angular/core';
- import { debug } from 'util';
- @Component({
- selector: 'app-root',
- templateUrl: './app.component.html',
- styleUrls: ['./app.component.css']
- })
- export class AppComponent {
- tweet = {
- likesCount: 10,
- isLiked: true
- }
- }
- <like
- [totalLikes]="tweet.likesCount"
- [isActive]="tweet.isLiked"
- ></like>
Now let’s test the results
And they’re working fine.
Conclusion
Here we’ve seen component APIs as input and output properties. We use these component APIs for reusing it again in our custom component as well. With the help of Input properties we can take the parameter values and with output properties we handle the event handlers. We have seen how to make the alias of Input and Output properties and how much they are useful for us. Because if we don’t apply alias and when we refactor our code then the code will be broken. So always it is the best approach to use alias. We’ve seen template and templateUrl where we define our component html. And then we just place our component selector in the html where we want to render this component. We’ve seen how we can apply the styles and how Angular follows the Shadow DOM inside View Encapsulation. This is how we can separate the things of different components. And they never override each other. Here we’ve seen how we can pass the data to the events. We’ve discussed ng-Content directive and how we use it to generate the dynamic html. But with ng-content there are different others html elements also created in the DOM which makes our code little bit dirty because actually these html elements are unnecessary. We don’t really need them so we use ng-container. With the help of ng-container we just render the content, and if we inspect the element we’ll see our code is very clean.
This is how the things works and we make the reusable components in Angular.

test testPosted Mar 15, 2019, 3:27 PM
Perfect. i understand angular with you series post. thanks very much
Mahesh ChandPosted Sep 5, 2018, 7:59 PM
Wow! Very detailed. Nicely done. I'm not an Angular developer but looks like you've done a great job and spend ton of time on this article. I've updated the title with "In Angular" so if someone searches in Google will probably search that. Cheers!