Creating Your First Angular 2 Components

Free Course

Getting Started with Angular 2

Angular 2 is the shiny new framework that comes with a lot of new concepts. Learn all the great new features.

With the release of Angular 2 just around the corner, it's important to have a grasp on the different concepts that this framework makes use of. Otherwise, it can be very easy to get confused while sifting through an Angular 2 project. In hopes of eliminating some of this confusion, I decided to create this article on the building block of Angular 2: the Component Directive (a.k.a. component).

To best illustrate this process, this post will take readers through the process of creating a top-level AppComponent, as well as a nested component. Throughout this process, we are going to learn a great deal about integral parts of Angular spanning from its template syntax to its use of dependency injection.

The end goal of this tutorial is to create the Angular 2 application below.

By the end of this tutorial, we will have a firm understanding of all of the different properties we can use to define components in Angular 2.

Before we begin working directly with components, let's quickly discuss why the Angular core development decided to make them the core part of the framework.

Components vs. Directives in Angular 1

The world of web development has changed tremendously 2009, which was the year when Angular 1 initially released. Among the trends that continually rose during this time was the use of web components. When used, web components allow developers to gain total control over their webpage by providing highly functional templates that are encapsulated within custom HTML selectors.

Web Components

After noticing their power, the Angular framework migrated from directives to components in Angular 2;

Components are simply directives that are always associated with a direct template.

This connection between the code and the template helps eliminate problems in Angular 1.x that developers were faced with. Among the more notable differences is the elimination of concepts like $scope and transclusion, which often made developing applications in Angular 1 a painful process.

Like HTML5 spec web components, Angular 2 components have an extremely well defined life-cycle. As a result of this we can specify when different callback functions happen depending upon the state of a component. (Ex. Making a get request to pulls data into a page once a component is initialized.)

When working with Angular components, we can make use of interfaces, like ngOnInit and ngOnDestroy, which allow us to implement functionality for different times in a components lifecycle.

That being said, these interfaces Angular 2 provides developers with can be tremendously helpful and further show the ability to have complete control over any of our application's components.

Development Environment

Developing Angular 2 applications takes a bit of setup. You need to do things like:

  • Grab all dependencies with npm
  • Setup a transpiler. TypeScript in our case
  • Start a server using something like lite-server

While we'll go over setting up an Angular 2 application in another article, feel free to use the following blank Plunkr to start building your Angular 2 components. h1VOj4EjUdeiQkyZY6v0 Starter Plunkr and Dev Environment

Building a Top-Level Component

Applications built in Angular 2 always have a top-level component where all of the functionality lies, so let's get started by looking at this component and then go through the code line-by-line.

// app/app.ts 

/** 
 ** First, we need to: 
 **  1a. import the Component class from @angular/core library
 **  1b. import the bootstrap method from @angular/platform-browser-dynamic to load our web app
 */ 
import { Component } from '@angular/core';                // 1a
import { bootstrap } from '@angular/platform-browser-dynamic';   // 1b

/**
 ** 2a. Pass in the name for the HTML class selector (<my-app></my-app>)
 ** 2b. Set the styles of our component using the styles options
 ** 2c. Define our component's template inline, rather than using the templateUrl option to access an external file. 
 **/ 
@Component({
    // 2a
    selector: 'my-app',

    // 2b
    styles: [`
        h1 {
    color:#545454;
    background:#02A8F4;
    padding:15px;
    box-shadow:2px 2px 2px 0 rgba(0, 0, 0, 0.3);
    }
    `] 

    // 2c
    template: `
    <h1>Hello from the {{componentName}}.</h1>
    `
})

/** 
 ** 3a. export our component so that it can be imported to othr files
 **
 **/
export class AppComponent {
    componentName: 'AppComponent'
}
bootstrap(AppComponent);

Let's break each step down so we can get a full understanding of how Angular 2 uses components.

Step 1: Import the Component Object

import { Component } from '@angular/core'

Angular 2 make use of the ES2015 module syntax (also known as ES6). For those unfamiliar with the syntax, it makes use of import statements to access different pieces of code. In addition the these import statements, this syntax also relies upon export statements to make code accessible to the rest of our application**.

When working with Angular 2, we will see these import statements being used to gain access to core features the framework through different Angular 2 libraries. In the code block we just looked at, we see the import statement telling Angular that we want to access the Component decorator from the @angular/core library, which is one of the main libraries Angular 2 utilizes.

Below, we can check out some of the other APIs that are central to developing web applications in Angular 2.0.

@angular/http

As you may have guessed, this library gives us access to all of Angular 2's functionality regarding http requests. The following script is required when using the http library.

<script src="node_modules/@angular/bundles/http.dev.js"></script>

This library is a vital part of the framework. Often times we will see the HTTP_PROVIDERS constant being imported from the @angular/http library. Once imported, this variable can be passed into our component as a provider, which will grant that component access to the Angular 2's core functionality.

@angular/common

The @angular/common is frequently used to deal with form building. This library holds lies FORM_DIRECTIVES constant which gives developers access to important directives like NgForm and NgFormModel.

The common library also provides developers with the validator and control functions, which can be used together to perform form validations. Angular and form validation is one of our favorite things here at Scotch, so you'll be sure to see an article coming soon on Angular 2 form validation.

@angular/router

The @angular/router libraries hold all of the code necessary to implement client-side routing. The following script is required:

<script src="node_modules/@angular/bundles/router.dev.js"></script>

The @angular/router is used to access the features like the @RouterConfig[] decorator and the RouterLink Directive.

When working in Angular 1.x, we were forced to use entire libraries (such as ngMessages), and this resulted in poor performance since we had to load the entire library for all our pages. To help ease this, the ES2015 module syntax allows us to decouple parts of a library, such as @angular/core, and access only the sections of code that we need.

Step 2: Add Meta-data to our Component using TypeScript Decorators

Once the Component object is imported, we can then begin describing our component using TypeScript's @ symbol. By checking out Angular 2's API guide, we can see that decorators are used to create new instances of @Directive, @Injectable, @RouterConfig and more.

A Quick Note On Decorators

When building applications with Angular 2, we will be using the @ decorator all the time to create dif. In our example, we are using this decorator to create a new component. Once Angular sees this, it will know that we want to create a new instance of a component, and it will create our component according to our configuration.

// app/app.ts
import { Component } from '@angular/core'

@Component({
    selector: 'my-app',
    providers: [],
    services: [],
    styles: [`
        h1 {
    color:#545454;
    background:#02A8F4;
    padding:15px;
    box-shadow:2px 2px 2px 0 rgba(0, 0, 0, 0.3);
    }
    `] 
    template: `
    <h1 class="main-text">Hello from the {{ componentName }}.</h1>
    `
})

Angular 2 Metadata

The main objective of these decorators is to allow us to add meta-data to our application that will tell Angular 2 how to process a class.

When building Angular components, we are able to configure the following options:

  • selector - defines the name of the HTML tag where this component will live. In this case, our component will by shown through the <my-app></my-app> tags.
  • providers - This is where we pass in any services that that want a component to access. We won't be getting into services in this article, however they are used to handle data and play the part of services, providers, and factories Angular 1.
  • directives - We use the directive option when we want to access another component directive. Because this is the top-level component, we often see components being passed into this option, and we will see how this works shortly
  • styles - The styles option is used to style a specific component. One of the advantages of using components is their ability to encapsulate their styles. We could have just as easily linked to an external stylesheet by using the styleUrls property. We should note that an array of stylesheets can be passed into this option.
  • template - This is the portion of our component that holds our template. It is an integral part of the component as it allows us to tie logic from our component directly to a view. When defining a template, we can either write it inline, or we can opt to use templateUrl to link to an external template.

Now that we've defined all the parts of our component, the last step is to export it so it can be used in other parts of our application.

Step 3: Export the Component

The exported class is where we can define any variables or functions that our component's template will be using:

// app/app.ts
export class AppComponent {
    componentName: 'AppComponent'
}

As we learned earlier, Angular 2 makes use of the ES2015 module syntax. By using the export statement, this component can be imported into different files in a project so it is a pivotal part of Angular 2.

Step 4: bootstrap our Component

// app/app.ts
import { bootstrap } from '@angular/platform-browser-dynamic'
/** 
  @Component Configuration
 **/    
bootstrap(AppComponent)

In Angular 1, we used the ng-app directive to bootstrap Angular applications. In Angular 2, applications rely upon the bootstrap method to load top-level components.

Angular 2 was built with the intentions of being completly decoupled from the DOM. We can just as easily run our application as a web-worker; however, we are using the framework to build a web application so we need to import this platform specific method from @angular/platform-browser-dynamic.


Angular 2 for Mobile Applications

We called bootstrap() from the @angular/platform-browser-dynamic library. So does this mean we can use a different bootstrap method for different platforms? Absolutely!

NativeScript is a runtime for build mobile applications created by Telerik. The Nativescript team has created the nativescript-angular library which I highly recommend checking out! This librarly grants us the nativeScriptBootstrap() method, which allows developers to leverage the Angular framework to build Native mobile applications.

To learn more about how Angular 2 can be used to build NativeScript applications, you can check out the following links:


Back to bootstrapping; by passing in the name of our component to the this method, we are bootstrapping our AppComponent, and we can pretty much think of this as a fancy word for loading; however, we do need to note that the bootstrap() method vital part of Angular 2 as it loads our top-level component.

When working with large applications, it is best practice to keep this bootstrap method in a file of its own because the main component will often be accompanied by other providers that the app may depend upon, however placing it inside this file was appropriate in the context of this getting started article.

And thus concludes our first look at a component in Angular 2. Once our app is bootstrapped, we can then add the appropriate HTML tags to our index.html file:

    <my-app>Loading ngFor Demo ...</my-app>

Watch as it appears! Although we're not done just yet, we can see a live demo of this in plnkr below.

At this point in our tutorial, the code for our component should replicate the block below:

//app/app.ts
import { Component } from '@angular/core';
import { bootstrap } from '@angular/platform-browser-dynamic';

@Component({
  selector: 'my-app',
  styles: [`
  h1 {
    color:#545454;
    background:#02A8F4;
    padding:15px;
    box-shadow:2px 2px 2px 0 rgba(0, 0, 0, 0.3);
  }
  `]
  template: `
  <div>
  <h1>Hello from the {{componentName}}.</h1>
  </div>
  `
})
export class AppComponent {
  componentName: 'AppComponent'
}
bootstrap(AppComponent)

Nesting A Child Component

Now that we have created a top-level component, let's take this one step further by creating a child component.

Let's look at doing the following with our child component:

  • Use Angular 2's built-in directives (not to be confused with Components)
  • Use a service to get data
  • Loop over that data in our template

This section is going to take a look at Angular 2's new template syntax and show the basics of Dependency Injection and working with services.

The file structure for this project is going to look like the tree below. So far in our project we have created the app/app.ts files, however we are now going to add the following friend.component.ts and friend.service.ts files.

**|-- app/friend.component.ts
|-- app/friend.service.ts**
|-- app/app.ts
|-- index.html
|-- config.js

Defining the Child Component Template

To get started, I am going to tell Angular that I want this component to live inside of <my-friends></my-friends>. The template attached to this component is going to use the ngFor structural directive to iterate over a list of names.

Angular 2 Template Syntax

ngFor is the new ng-repeat

The ngFor directive is the successor to ng-repeat, one of Angular 1.x's most popular directives. In addition to ngFor, Angular 2 provides developers with a handful of other camel-case directives that come in the form of:

In this example, we are going to make use of ngFor, which is a structural directive. A structural directive is a directive that modifies the structure of the DOM.

Below we have the code for our template. In addition to the ngFor statement, I am also going to create another componentName variable just like we saw in the AppComponent example. We can use the same variable name and not have to worry about it messing with other components that utilize the same naming conventions.

// app/friend.component.ts
import { Component } from '@angular/core'; 

@Component({
    selector: 'my-friends'
    template: `
        <h1>Hello from the {{ componentName }}!</h1>
        <div *ngFor="#f of friends">
            <h3>Name: {{ f.name }}</h3> 
            <h4>Age: {{ f.age }}</h4> 
        </div>
    `
})

Whenever we see an asterisk (*) prepended onto a directive, we immediately know that this is will be using templates tags (<template></template>) to render this piece of code.

This ability to use symbols to create dynamic behavior is what Angular calls "syntactical sugar". It makes the process of developing web applications a quicker process by cutting out bits of unnecessary code without cluttering up our template.

Let's take a look at some other symbols that we will come across when working with Angular 2.


Angular 2 Syntax Overview

Local Variables #

The pound symbol (# is used to declare a local variable in our templates. When working with templates in Angular 2, we can use this symbol to reference different DOM elements in our application. These local variables will act as references to specific DOM elements. Moreover, they provide us with the ability to do things like pull values from input fields and add dynamic functionality to a DOM element.

    <div *ngFor="#f of friends">

Event Bindings ()

In Angular 1.x, we had to rely on directives like ng-click, ng-blur, ng-mouseenter, to handle different events. Angular 2 has dropped all of these directives and implemented a new, powerful syntax that allows developers to bind to any valid DOM event. For example:

By passing in the name of the event into parenthesis, which signifies an event binding in Angular 2. When working with events in Angular, it's important to know that events flow out of the template to the component.

    <a (click)="doSomething()">Doing Something Button</a>

Property Binding []

On the opposite side of event bindings (()) lie Angular's square-bracket syntax ([]) which signify a property binding.

When working with property bindings, any values flow from the component class to the template, whereas event bindings work vice-versa.

When working with Angular 1.x, we had to use directives like ng-src and ng-href to dynamically pass in values to DOM elements, however the use of property bindings allows us to drop the ng- prefix, and simply pass in the name of the property we wish to define.

    <img [src]="someUrl">

The use of property bindings is particularly key when define attribute directives. For example, we can use the following syntax when working with NgStyle

    <div [style.background]="colorValue"></div>

Now that we've learned a little bit about Angular's new template syntax, lets get back to our example and add some styles to our child component.


Child Component Styles

The first thing we'll do is style the div that contains the ngFor that iterates over through the friends loop so that it creates individual cards for each person with some space between them. When we nest this component, we will wrap our main component's template in a div to see how the styling of a component will only have an effect on the template with which it is attached.

In addition to the div class, we are also going to style the h1 so that the text aligns to the center of the page. Soon, we are going to see how these styles do not bleed into other components. For those who wish to learn more about styling components in Angular 2, you can check out our tutorial on styling components in Angular 2.

// app/friend.component.ts
    selector: 'my-friends' ,
    styles: [`
     div { 
     background-color:#EFEFEF;
     margin-bottom:15px;
     padding:15px;
     border:1px solid #DDD;
     box-shadow:2px 2px 2px 0 rgba(0, 0, 0, 0.3);
    border-radius:3px;
  }
  h2 { 
    text-align: center;
  }
  `]

Export the FriendComponent Class

Once our styles are set, we need to export our newly made component using the export class .. statement. Inside this class, I am going to create a friends object which will contain name and age properties that ngFor will iterate over.

// app/friend.component.ts
export class FriendComponent {
    componentName: 'FriendComponent';
    friends = [
        { age: 40, name: 'Jordan Houston' },
    { age: 23, name: 'Josh Beh' },
    { age: 23, name: 'Joseph Canina' },
    { age: 24, name: 'Alexandra Wilkins' },
    { age: 22, name: 'Kiersten Costanzo' },
    { age: 23, name: 'Ku Sherwood' },
    { age: 25, name: 'Arta Halili' },
    { age: 21, name: 'Patrick Cooney' },
    { age: 21, name: 'Z.A. Perr' },
    { age: 18, name: 'Tyler Mulligan' },
    { age: 26, name: 'Dennis Dempsey' },
    { age: 32, name: 'Francis Yeager' },
    { age: 23, name: 'Phil Belardi' },
    { age: 25, name: 'Bryan Roman' }
    ];
} 

Before we move forward, we have to take a quick detour and update our FriendComponent so that we can access this data.

Detour: Refactoring FriendComponent Class to use @Injectable()

We usually access data by using services and often times these services make use of another amazing feature of Angular 2: Dependency Injection and the use of @Injectable. To understand the basics of how this works, let's move our friends object so that it lies within a file located at app/friend.service.ts.

The final code for this file is going to look like the block below.

// app/friend.service.ts

// Step 1. Import Injectable Decorator
import { Injectable } from '@angular/core';

// Step 2. Use @Injectable() to declare the FriendSerivce class as an Injectable
@Injectable()

/** 
    Step 3A. - Create and export FriendsService  Class { }
    3B: create friends object and declare it to be an Array of any values/ 
    3C: Add friends object to the constructor function
    3D: create getFriends() function to call all friends values. 
**/
// 3A
export class FriendService { 

    // 3B 
    friends:Array<any>;

    // 3C
    constructor() {
        this.friends = [
            { age: 40, name: 'Jordan Houston' },
    { age: 23, name: 'Josh Beh' },
    { age: 23, name: 'Joseph Canina' },
    { age: 24, name: 'Alexandra Wilkins' },
    { age: 22, name: 'Kiersten Costanzo' },
    { age: 23, name: 'Ku Sherwood' },
    { age: 25, name: 'Arta Halili' },
    { age: 21, name: 'Patrick Cooney' },
    { age: 21, name: 'Z.A. Perr' },
    { age: 18, name: 'Tyler Mulligan' },
    { age: 26, name: 'Dennis Dempsey' },
    { age: 32, name: 'Francis Yeager' },
    { age: 23, name: 'Phil Belardi' },
    { age: 25, name: 'Bryan Roman' }
        ];
    }

    // 3D
    getFriends() {
        return this.friends;
    }

}
  1. The first thing we need to do is import Injectable from the @angular/core library.
  2. Once that is imported, we then need to declare this class to be an injectable using the Injectable() decorator we just imported. When implemented, @Injectable() decorator will tell that Angular a class need to be used for depedency injection.
// app/friend.service.ts
import { Injectable } from '@angular/core'
@Injectable()

3a. We create our FriendService class which will wrap all of the code we want our FriendComponent to access. 3b. We create a friends variables, and use TypeScript's type-system to tell Angular that this object is going to be an array. 3c. We add our data to the friends object by adding it into our constructor function, which is where we put the data we want a particular class to receive.
3d. Lastly, we create a getFriends function to return our array of items. This is where we will often see http calls being made however our data is internal, therefore we can leave out having to import the @angular/http library.

Modifying Our FriendComponent File

Once our service is created, we need to do a few things in order to access it into our component. Let's import the service into our app/friend.component.ts file.

// app/friend.component.ts
import { Component } from '@angular/core';

// NEW ==> We need to import FriendService into our component   
import { FriendService } from 'app/friend.service';

Register the Service as A Provider

The next thing we need to do is pass FriendService into our components providers option. As we learned earlier, this is the section of our component where we add any services that it makes use of.

// app/friend.component.ts
@Components({
  selector: 'my-friends',
  providers: [FriendService],
  styles: /** Styles are placed here **/
})

Inject it into our constructor() function

In order for our template to access the FriendService, we must inject it into the components constructor function. In this example, we are going to set our FriendService equal to _friendService.

Once it's added to our constructor function, we are going to finish things off by assigning the friends variable the result of our getFriends() function.

// app/friend.component.ts
export class FriendComponent {
    componentName: 'FriendComponent';

    // Inject FriendService and assign it to _friendService
    constructor(private _friendService: FriendService) {
        // Utilize .get request from app/friend.service.ts to populate friends object
        this.friends = _friendService.getFriends();
    }
}

Once things are all said in done, the final code for our app/friend.component.ts should look like the block below:

// app/friend.component.ts
import { Component } from '@angular/core';
import { FriendService } from 'app/friend.service';

@Component({
    selector: 'my-friends',
    providers : [FriendService],
    styles: [`
         div { 
     background-color:#EFEFEF;
     margin-bottom:15px;
     padding:15px;
     border:1px solid #DDD;
     box-shadow:2px 2px 2px 0 rgba(0, 0, 0, 0.3);
    border-radius:3px;
  }
  h2 { 
    text-align: center;
  }
    `]
    template: `
        <h2>Hello from the {{componentName}}!</h2>
        <div *ngFor="#f of friends">
        <h4> Name : {{f.name}} </h4> <h4>Age: {{f.age}}</h4> 
        </div>
    `
})
export class FriendComponent {
    componentName: 'FriendComponent';

    // Inject FriendService and assign it to _friendService
    constructor(_friendService: FriendService) {
        // Utilize .get request from app/friend.service.ts to populate friends object
        this.friends = _friendService.getFriends();
    }
}

Additionally, the final code for our app/friend.service.ts file should replicate the following code.

// app/friend.service.ts
// Step 1. Import Injectable Decorator
import { Injectable } from '@angular/core';

// Step 2. Use @Injectable() to declare FriendsSerivce to be used in DI/
@Injectable()

/** 
    Step 3A. - Create and export FriendsSerivce  Class { }
    3B - create friends object and declare it to be an Array of any values/ 
    3C Add friends object to the constructor function
    3D: create getFriends() function to call all friends values. 
**/ 

 // 3A
export class FriendService { 

    // 3B 
    friends:Array<any>;

    // 3C
    constructor() {
        this.friends = [
            { age: 40, name: 'Jordan Houston' },
            { age: 23, name: 'Josh Beh' },
            { age: 23, name: 'Joseph Canina' },
            { age: 24, name: 'Alexandra Wilkins' },
            { age: 22, name: 'Kiersten Costanzo' },
            { age: 23, name: 'Ku Sherwood' },
            { age: 25, name: 'Arta Halili' },
            { age: 24, name: 'Patrick Cooney' },
            { age: 23, name: 'Z.A. Perr' },
            { age: 18, name: 'Tyler Mulligan' },
            { age: 26, name: 'Dennis Dempsey' },
            { age: 32, name: 'Francis Yeager' },
            { age: 23, name: 'Phil Belardi' }
        ];
    }

    // 3D
    getFriends() {
        return this.friends;
    }
}

Now that we have successfully created a child-component, we will finish this tutorial off by nesting it into our main AppComponent

Adding FriendComponent to AppComponent

Now that our second component is wired up, we are ready to nest it within our top-level component. To accomplish this, we need to make a few modifications to our app.ts file.

We have already seen how we can import core parts of Angular 2 via the ES2015 module syntax. Now, lets check out how we can use these same import statements to access code inside of our project.

// app/app.ts

import { Component } from '@angular/core';
import { bootstrap } from '@angular/platform-browser-dynamic';

/** Nested Component */ 
import { FriendComponent } from 'app/friend.component';

Once our component is imported into the file, we then need to modify the sections of our @Component instance:

In order to access FriendComponent, we need to add it into the components directive array.

// app/main.component.ts
    directives: [FriendComponent]

We need to add <my-friends></my-friends> to our inline-template or else it's not going to render. In addition to adding this tag, I also want to I also want to wrap this template in the <div> tag that I spoke about earlier to further show Angular 2's style encapsulation.

Now, our code should show:

// app/app.ts
import { Component } from '@angular/core';
import { bootstrap } from '@angular/platform-browser-dynamic';
/** Nested Component */ 
import { FriendComponent } from 'app/friend.component';
@Component({
    selector: 'my-app',
    directives: [FriendComponent],
    styles: [`
        h1 {
            color:#545454;
    background:#02A8F4;
    padding:15px;
    box-shadow:2px 2px 2px 0 rgba(0, 0, 0, 0.3);
        }
    `]
    template: `
    <div>
        <h1>Hello from the {{ componentName }}.</h1>
        <my-friends></my-friends>
    </div>
    `
})
export class AppComponent {
    componentName: 'AppComponent';
}
bootstrap(AppComponent)

Checking out the Component

By taking a look at our code, we see that we have successfully nested our FriendComponent within our top-level AppComponent. Additionally, we learned a great deal about components, and the different parts that going into building them and tying them together, which is crucial when workiing with Angular 2.

In most cases, the component we nested into AppComponent will be also parent component that may consist of any number of children. We just saw how easy Angular makes the process of establishing this relationship.

Specifically, we learned that we only need to pass them in as a directive into the parent components where they are being utilized. From there, the parent component will carry any of the templates associated with its child components as well with the functionality that goes along with it, and as a result of this, the child component will be rendered wherever and whenever it's parent component is instatiated.

It's a simple process, yet it is still unbeliably effective. I hope you've learned at least something new about Angular 2's use of components in addition to gaining some knowlegde regarding the rest of the framework!

As Angular 2 continues its final stride towards production, the attainment of all of this new knowledge will surely pay off in the long run.

Thomas Greco

I'm a web application developer living in New York City. I love using new technologies and teaching people about these technologies through my past experiences.

Before falling in love with programming, I worked in graphic design, and I continue to rely my background in design when building web applications. That said, I have a huge love for Sass CSS, SVG Animation, and much, much, more!

Want to get in touch with me? Reach out to me via sassmasterTG and we will get connected ASAP :)