Learning Angular - Second Edition

4.2 (10 reviews total)
By Christoffer Noring , Pablo Deeleman
  • Instant online access to over 7,500+ books and videos
  • Constantly updated with 100+ new titles each month
  • Breadth and depth in over 1,000+ technologies
  1. Creating Our First Component in Angular

About this book

The latest version of Angular comes with a lot of new features that help you to make your applications smaller and faster. This book will show you how to set up an Angular project, and you’ll build Angular components right from the beginning.

Moving on, you’ll explore and work with the components to build your app. Next, you’ll find out more about TypeScript and see how to use it to build apps in the best way possible. You’ll then be introduced to the building blocks - Properties, Events, Directives, and Pipes - and how it can be used to implement and enhance the components.

Additionally, you’ll be using Angular components to organize your components in a scalable way. Then you’ll understand how to get data in your app and add navigation to it. Furthermore, you’ll deep dive and work with Forms, Authentication, and see how Material design will help you make your app beautiful in just a few short lines of code. Lastly, you’ll see how to use animating components with Angular, and test and debug the app.

All in all, the overall mission is to give you a great start when developing apps using Angular and TypeScript.

Publication date:
December 2017
Publisher
Packt
Pages
456
ISBN
9781787124929

 

Chapter 1. Creating Our First Component in Angular

When it comes to Angular development, there are some things that are good to know and some things that we need to know to embark on our great journey. One of the things that is good to know is semantic versioning. This is good to know because it is the way the Angular team has chosen to deal with changes. This will hopefully make it easier to find the right solutions to future app development challenges when you go to https://angular.io/ or Stack Overflow and other sites to search for solutions. 

Another important, but sometimes painful, topic is that of project setup. It is a necessary evil that needs to be done in the beginning of a project, but getting this right early on can reduce a lot of friction as your application grows with you. Therefore, a large part of this chapter is dedicated to demystifying and enabling you as a developer to save you from future frustrations and migraines.

We will also be able to create our first application at the end of this chapter and get a feel for the anatomy of an Angular application. To sum up, here are the main themes that we will explore in this chapter.

In this chapter, we will:

  • Learn about semantic versioning, why it matters, and Angular's take on it
  • Discover how we set up our project using Angular CLI
  • Create our first application and begin to understand the core concepts in Angular
 

It's just Angular – introducing semantic versioning


Using semantic versioning is about managing expectations. It's about managing how the user of your application, or library, will react when a change happens to it. Changes will happen for various reasons, either to fix something broken in the code or add/alter/remove a feature. The way authors of frameworks or libraries use to convey what impact a certain change has is by incrementing the version number of the software.

A production-ready software usually has version 1.0 or 1.0.0 if you want to be more specific.

There are three different levels of change that can happen when updating your software. Either you patch it and effectively correct something. Or you make a minor change, which essentially means you add functionality. Or lastly you make a major change, which might completely change how your software works. Let's describe these changes in more detail in the following sections.

Patch change

A patch change means we increment the right most digit by one. Changing the said software from 1.0.0 to 1.0.1 is a small change, usually a bug fix. As a user of that software you don't really have to worry; if anything, you should be happy that something is suddenly working better. The point is, you can safely start using 1.0.1.

Minor change

This means the software is increased from 1.0.0 to 1.1.0. We are dealing with a more severe change as we increase the middle digit by one. This number should be increased when functionality is added to the software and it should still be backwards compatible. Also in this case it should be safe adapting the 1.1.0 version of the software.

Major change

At this stage, the version number increases from 1.0.0 to 2.0.0. Now this is where you need to look out. At this stage, things might have changed so much that constructs have been renamed or removed. It might not be compatible to earlier versions. I'm saying it might because a lot of software authors still ensure that there is a decent backwards compatibility, but the main point here is that there is no warranty, no contract, guaranteeing that it will still work.

What about Angular?

The first version of Angular was known by most people as Angular 1; it later became known as AngularJS. It did not use semantic versioning. Most people actually still refer to it as Angular 1.

Then Angular came along and in 2016 it reached production readiness. Angular decided to adopt semantic versioning and this caused a bit of confusion in the developer community, especially when it was announced that there would be an Angular 4 and 5, and so on. Google, as well as the Google Developer Experts, started to explain to people that it wanted people to call the latest version of the framework Angular - just Angular. You can always argue on the wisdom of that decision, but the fact remains, the new Angular is using semantic versioning. This means Angular is the same platform as Angular 4, as well as Angular 11, and so on, if that ever comes out. Adopting semantic versioning means that you as a user of Angular can rely on things working the same way until Google decides to increase the major version. Even then it's up to you if you want to remain on the latest major version or want to upgrade your existing apps.

 

A fresh start


As mentioned before, Angular represents a full rewrite of the AngularJS framework, introducing a brand new application architecture completely built from scratch in TypeScript, a strict superset of JavaScript that adds optional static typing and support for interfaces and decorators.

In a nutshell, Angular applications are based on an architecture design that comprises of trees of web components interconnected by their own particular I/O interface. Each component takes advantage under the covers of a completely revamped dependency injection mechanism.

To be fair, this is a simplistic description of what Angular really is. However, the simplest project ever made in Angular is cut out by these definition traits. We will focus on learning how to build interoperable components and manage dependency injection in the next chapters, before moving on to routing, web forms, and HTTP communication. This also explains why we will not make explicit references to AngularJS throughout the book. Obviously, it makes no sense to waste time and pages referring to something that will not provide any useful insights on the topic, besides the fact we assume that you might not know about Angular 1.x, so such knowledge does not have any value here.

Web components

Web components is a concept that encompasses four technologies designed to be used together to build feature elements with a higher level of visual expressivity and reusability, thereby leading to a more modular, consistent, and maintainable web. These four technologies are as follows:

  • Templates: These are pieces of HTML that structure the content we aim to render
  • Custom elements: These templates not only contain traditional HTML elements, but also the custom wrapper items that provide further presentation elements or API functionalities
  • Shadow DOM: This provides a sandbox to encapsulate the CSS layout rules and JavaScript behaviors of each custom element
  • HTML imports: HTML is no longer constrained to host HTML elements, but to other HTML documents as well

In theory, an Angular component is indeed a custom element that contains a template to host the HTML structure of its layout, the latter being governed by a scoped CSS style sheet encapsulated within a shadow DOM container. Let's try to rephrase this in plain English. Think of the range input control type in HTML5. It is a handy way to give our users a convenient input control for entering a value ranging between two predefined boundaries. If you have not used it before, insert the following piece of markup in a blank HTML template and load it in your browser:

<input id="mySlider" type="range" min="0" max="100" step="10">

You will see a nice input control featuring a horizontal slider in your browser. Inspecting such control with the browser developer tools will unveil a concealed set of HTML tags that were not present at the time you edited your HTML template. There you have an example of shadow DOM in action, with an actual HTML template governed by its own encapsulated CSS with advanced dragging functionality. You will probably agree that it would be cool to do that yourself. Well, the good news is that Angular gives you the toolset required for delivering this very same functionality, so we can build our own custom elements (input controls, personalized tags, and self-contained widgets) featuring the inner HTML markup of our choice and our very own style sheet that does not affect (nor is impacted) by the CSS of the page hosting our component.

Why TypeScript over other syntaxes?

Angular applications can be coded in a wide variety of languages and syntaxes: ECMAScript 5, Dart, ECMAScript 6, TypeScript, or ECMAScript 7.

TypeScript is a typed superset of ECMAScript 6 (also known as ECMAScript 2015) that compiles to plain JavaScript and is widely supported by modern OSes. It features a sound object-oriented design and supports annotations, decorators, and type checking.

The reason why we picked (and obviously recommend) TypeScript as the syntax of choice for instructing how to develop Angular applications in this book is based on the fact that Angular itself is written in this language. Being proficient in TypeScript will give the developer an enormous advantage when it comes to understanding the guts of the framework.

On the other hand, it is worth remarking that TypeScript's support for annotations and type introspection turns out to be paramount when it comes to managing dependency injection and type binding between components with a minimum code footprint, as we will see further down the line in this book.

Ultimately, you can carry out your Angular projects in plain ECMAScript 6 syntax if that is your preference. Even the examples provided in this book can be easily ported to ES6 by removing type annotations and interfaces, or replacing the way dependency injection is handled in TypeScript with the most verbose ES6 way.

For the sake of brevity, we will only cover examples written in TypeScript and actually recommend its use because of its higher expressivity thanks to type annotations, and its neat way of approaching dependency injection based on type introspection out of such type annotations.

 

Setting up our workspace with Angular CLI


There are different ways to get started, either using the Angular quickstart repository on the https://angular.io/ site, or installing the scaffolding tool Angular CLI, or lastly, you could use Webpack to set up your project. It is worth pointing out that the standard way of creating a new Angular project is through using Angular CLI and scaffold your project. Systemjs, used by the quickstart repository, is something that used to be the default way of building Angular projects. It is now rapidly diminishing, but it is still a valid way of setting up an Angular project. The interested reader is therefore recommended to check the Appendix A, SystemJS for more information on it.

Setting up a frontend project today is more cumbersome than ever. We used to just include the necessary script with our JavaScript code and a link tag for our CSS and img tag for our assets and so on. Life used to be simple. Then frontend development became more ambitious and we started splitting up our code in modules, we started using preprocessors for both our code and CSS. All in all, our projects became more complicated and we started to rely on build systems such as Grunt, Gulp, Webpack, and so on. Most developers out there are not huge fans of configuration, they just want to focus on building apps. Modern browsers, however, do more to support the latest ECMAScript standard and some browsers have even started to support modules, which are resolved at runtime. This is far from being widely supported though. In the meantime, we still have to rely on tools for bundling and module support.

Setting up a project with leading frameworks such as React or Angular can be quite difficult. You need to know what libraries to import and ensure that files are processed in the correct order, which leads us into the topic of scaffolding tools. For AngularJS, it was quite popular to use Yeoman to scaffold up a new application quickly and get a lot of nice things preconfigured. React has a scaffolder tool called create-react-app, which you probably have saved and it saves countless hours for React developers. Scaffolder tools becomes almost a necessity as complexity grows, but also where every hour counts towards producing business value rather than fighting configuration problems.

The main motivation behind creating the Angular CLI tool was to help developers focus on app building and not so much on configuration. Essentially, with a simple command, you should be able to scaffold an application, add a new construct to it, run tests, or create a production grade bundle. Angular CLI supports all that.

Prerequisites

What you need to get started is to have Git and Node.js installed. Node.js will also install something called NPM, a node package manager that you will use later to install files you need for your project. After this is done, you are ready to set up your Angular application. You can find installation files to Node.js at https://nodejs.org.

The easiest way to have it installed is to go to the site:

https://nodejs.org/en/download/

Installing Node.js will also install something called NPM, Node Package Manager, which you will need to install dependencies and more. The Angular CLI requires Node 6.9.0 and NPM 3 or higher. Currently on the site, you can choose between an LTS version and the current version. The LTS version should be enough.

Installation

Installing the Angular CLI is as easy as running the following command in your Terminal:

npm install -g @angular/cli

On some systems, you may need to have elevated permissions to do so; in that case, run your Terminal window as an administrator and on Linux/macOS instead run the command like this:

sudo npm install -g @angular/cli

First app

Once the Angular CLI is in place the time has come to create your first project. To do so place yourself in a directory of your choice and type the following:

ng new <give it a name here>

Type the following:

ng new TodoApp

This will create a directory called TodoApp. After you have run the preceding command, there are two things you need to do to see your app in a browser:

  • Navigate to the just created directory
  • Serve up the application

This will be accomplished by the following commands:

cd TodoApp
npm start

At this point, open up your browser on http://localhost:4200 and you should see the following:

Testing

The Angular CLI doesn't just come with code that makes your app work. It also comes with code that sets up testing and includes a test. Running the said test is as easy as typing the following in the Terminal:

npm test

You should see the following:

How come this works? Let's have a look at the package.json file that was just created and the scripts tag. Everything specified here can be run using the following syntax:

npm run <key>

In some cases, it is not necessary to type run and it will be enough to just type:

npm <key>

This is the case with the start and test commands.

The following listing makes it clear that it is possible to run more commands than start and test that we just learned about:

"scripts": {
  "ng": "ng",
  "start": "ng serve",
  "build": "ng build",
  "test": "ng test",
  "lint": "ng lint",
  "e2e": "ng e2e"
}

So far we have learned how to install the Angular CLI. Using the Angular CLI we have learned to:

  1. Scaffold a new project.
  2. Serve up the project and see it displayed in a browser.
  3. Run tests.

That is quite an accomplishment. We will revisit the Angular CLI in a later chapter as it is a very competent tool, capable of a lot more.

 

Hello Angular


We are about to take the first trembling steps into building our first component. The Angular CLI has already scaffolded our project and thereby carried out a lot of heavy lifting. All we need to do is to create new file and starting filling it with content. The million dollar question is what to type?

So let's venture into building our first component. There are three steps you need to take in creating a component. Those are:

  1. Import the component decorator construct.
  2. Decorate a class with a component decorator.
  3. Add a component to its module ( this might be in two different places).

Creating the component

First off, let's import the component decorator:

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

Then create the class for your component:

class AppComponent {
  title:string = 'hello app';
}

Then decorate your class using the Component decorator:

@Component({
  selector: 'app',
  template: `<h1>{{ title }}</h1>`
})
export class AppComponent {  
  title: string = 'hello app';
}

We give the Component decorator, which is function, an object literal as an input parameter. The object literal consists at this point of the selector and template keys, so let's explain what those are.

Selector

A selector is what it should be referred to if used in a template somewhere else. As we call it app, we would refer to it as:

<app></app>

Template/templateUrl

The template or templateUrl is your view. Here you can write HTML markup. Using the   template   keyword, in our object literal, means we get to define the HTML markup in the same file as the component class. Were we to use templateUrl, we would then place our HTML markup in a separate file.

The preceding  example also lists the following double curly braces, in the markup:

<h1>{{ title }}</h1>

This will be treated as an interpolation and the expression will be replaced with the value of AppComponent's title field. The component, when rendered, will therefore look like this:

hello app

Telling the module

Now we need to introduce a completely new concept, an Angular module. All types of constructs that you create in Angular should be registered with a module. An Angular module serves as a facade to the outside world and it  is nothing more than a class that is decorated by the decorate @NgModule. Just like the @Component decorator, the @NgModule decorator takes an object literal as an input parameter. To register our component with our Angular module, we need to give the object literal the property declarations. The declarations property is of a type array and by adding our component to that array we are registering it with the Angular module. 

The following code shows the creation of an Angular module and the component being registered with it by being added to declarations keyword array:

import { AppComponent } from './app.component';

@NgModule({ 
 declarations: [AppComponent]
})
export class AppModule {}

At this point, our Angular module knows about the component. We need to add one more property to our module, bootstrap. The bootstrap keyword states that whatever is placed in here serves as the entry component for the entire application. Because we only have one component, so far, it makes sense to register our component with this bootstrap keyword:

@NgModule({
  declarations: [AppComponent],
bootstrap: [AppComponent]
})
export class AppModule {}

It's definitely possible to have more than one entry component, but the usual scenario is that there is only one. 

For any future components, however, we will only need to add them to the declarations property, to ensure the module knows about them.

So far we have created a component and an Angular module and registered the component with said the module. We don't really have a working application yet, as there is one more step we need to take. We need to set up the bootstrapping. 

Setting up a bootstrap file

The main.ts file is your bootstrap file and it should have the following content:

import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';

platformBrowserDynamic().bootstrapModule(AppModule);

What we do in the preceding code snippet is to provide the recently created module as an input parameter to the method call bootstrapModule(). This will effectively make the said module, the entry module of the application. This is all we need to create a working application. Let's summarize the steps we took to accomplish that:

  1. Create a component.
  2. Create a module and register our created component in its declaration property.
  3. Also register our component in the modules bootstrap property to make it serve as an application entry point. Future components we create just need to be added to the declarations property.
  4. Bootstrap our created module by using the said module as an input parameter to the bootstrapModule() method.

You as a reader have had to swallow a lot of information at this point and take our word for it. Don't worry, you will get a chance to get more acquainted with components in this chapter as well as Angular modules in upcoming chapters. For now, the focus was just to get you up and running by giving you a powerful tool in the form of the Angular CLI and show you how few steps are actually needed to have an app rendered to the screen.

 

Diving deeper into Angular components


We have come a long way now, from tapping on TypeScript for the first time to learning how to code the basic scripting schema of an Angular component. However, before jumping into more abstract topics, let's try to build another component so we really get the hang of how creating it really works.

Component methods and data updates

Create a new timer.component.ts file in the same folder and populate it with the following basic implementation of a very simple component. Don't worry about the added complexity, as we will review each and every change made after the code block:

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

@Component({
  selector: 'timer',
  template: `<h1>{{ minutes }}:{{ seconds }} </h1>>`
})
export class TimerComponent {
  minutes: number;
  seconds: number;

  constructor(){
    this.minutes = 24;
    this.seconds = 59;
  }
}

At this point, we have created a whole new component by creating the TimerComponent class and decorated it with @Component, just as we learned how to do in a previous section. We learned in the previous section that there is more to be done, namely to tell an Angular module that this new component exists. The Angular module is already created so you just need to add our fresh new component to its declarations property, like so:

@NgModule({
  declarations: [
    AppComponent, TimerComponent
  ],
  bootstrap: [AppComponent]
})

As long as we only had the AppComponent we didn't really see the point of having an Angular module. With two components registered with our module, this changes.  When a component is registered with an Angular module it becomes available to other constructs in the module. It becomes available to their template/templateUrl. This means that we can have TimerComponent rendered inside of our AppComponent.

Let's therefore go back to our AppComponent file and update its template to show just that:

@Component({
  selector: 'app',
  template: `<h1>{{ title }}</h1> <timer></timer>`
})
export class AppComponent {  
  title: string = 'hello app';
}

In the preceding code, we highlight in bold how we add the TimerComponent to the AppComponents template. Or rather we refer to the TimerComponent by its selector property name, which is timer.

Let's show the TimerComponent again, in it's entirety, and highlight the selector property because this is a really important thing to understand; that is, how to place a component in another component:

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

@Component({
selector: 'timer',
  template: `<h1>{{ minutes }}:{{ seconds }} </h1>>`
})
export class TimerComponent {
  minutes: number;
  seconds: number;

  constructor(){
    this.minutes = 24;
    this.seconds = 59;
  }
}

We want to do more than just display a handful of numbers, right? We actually want them to represent a time countdown, and we can achieve that by introducing these changes. Let's first introduce a function we can iterate on in order to update the countdown. Add this function after the constructor function:

tick() {
  if(--this.seconds < 0) {
    this.seconds = 59;
    if(--this.minutes < 0) {
      this.minutes = 24;
      this.seconds = 59;
    }
  }
}

Note

Selectors in Angular are case sensitive. As we will see later in this book, components are a subset of directives that can support a wide range of selectors. When creating components, we are supposed to set a custom tag name in the selector property by enforcing a dash-casing naming convention. When rendering that tag in our view, we should always close the tag as a non-void element. So <custom-element></custom-element> is correct, while <custom-element /> will trigger an exception. Last but not least, certain common camel case names might conflict with the Angular implementation, so avoid them.

Going from static to actual data

As you can see here, functions in TypeScript need to be annotated with the type of the value they return, or just void if none. Our function assesses the current value of both minutes and seconds, and then either decreases their value or just resets it to the initial value. Then this function is called every second by triggering a time interval from the class constructor:

constructor() {
  this.minutes = 24;
  this.seconds = 59;
  setInterval(() => this.tick(), 1000);
}

Here, we spot for the first time in our code an arrow function (also known as a lambda function, fat arrow, and so on), a new syntax for functions brought by ECMAScript 6, which we will cover in more detail in Chapter 3, Introducing TypeScript. The tick function is also marked as private, so it cannot be inspected or executed outside a PomodoroTimerComponent object instance.

So far so good! We have a working Pomodoro timer that countdowns from 25 minutes to 0, and then starts all over again. The problem is that we are replicating code here and there. So, let's refactor everything a little bit to prevent code duplication:

constructor() {
  this.reset();
  setInterval(() => this.tick(), 1000);
}

reset() {
  this.minutes = 24;
  this.seconds = 59;
}

private tick() {
  if(--this.seconds < 0) {
    this.seconds = 59;
    if(--this.minutes < 0) {
      this.reset();
    }
  }
}

We have wrapped the initialization (and reset) of minutes and seconds inside our function resetPomodoro, which is called upon instantiating the component or reaching the end of the countdown. Wait a moment though! According to the Pomodoro technique, Pomodoro practitioners are allowed to rest in between Pomodoros or even pause them should an unexpected circumstance get in the way. We need to provide some sort of interactivity so the user can start, pause, and resume the current Pomodoro timer.

Adding interactivity to the component

Angular provides top-notch support for events through a declarative interface. This means it is easy to hook up events and have the point to method. It's also easy to bind data to different HTML attributes, as you are about to learn.

Let's first modify our template definition:

@Component({
  selector: 'timer',
  template: `
    <h1>{{ minutes }}: {{ seconds }} </h1>
    <p>
      <button (click)="togglePause()"> {{ buttonLabel }}</button>
    </p>
  `
})

We used a multiline text string! ECMAScript 6 introduced the concept of template strings, which are string literals with support for embedded expressions, interpolated text bindings, and multiline content. We will look into them in more detail in Chapter 3, Introducing TypeScript.

In the meantime, just focus on the fact that we introduced a new chunk of HTML that contains a button with an event handler that listens to click events and executes thetogglePause()method upon clicking. This (click) attribute is something you might not have seen before, even though it is fully compliant with the W3C standards. Again, we will cover this in more detail in Chapter 4, Implementing Properties and Events in Our Components. Let's focus on thetogglePause()method and the newbuttonLabelbinding. First, let's modify our class properties so that they look like this:

export class TimerComponent {
  minutes: number;
  seconds: number;
  isPaused: boolean;
  buttonLabel: string;
  // rest of the code will remain as it is below this point
}

We introduced two new fields. The first is buttonLabel, which contains the text that will later on be displayed on our newly-created button. isPaused is a newly-created variable that will assume a true/false value, depending on the state of our timer. So, we might need a place to toggle the value of such a field. Let's create the togglePause() method we mentioned earlier:

togglePause() {
  this.isPaused = !this.isPaused;
  // if countdown has started
  if(this.minutes < 24 || this.seconds < 59) {
    this.buttonLabel = this.isPaused ? 'Resume' : 'Pause';
  }
}

In a nutshell, the togglePause() method just switches the value of isPaused to its opposite and then, depending on such a new value and whether the timer has started (which would entail that any of the time variables has a value lower than the initialisation value) or not, we assign a different label to our button.

Now, we need to initialize these values, and it seems there is no better place for it. So, the reset() function is the place where variables affecting the state of our class are initialized:

reset() {
  this.minutes = 24;
  this.seconds = 59;
  this.buttonLabel = 'Start';
  this.togglePause();
}

By executing togglePause() every time, we reset it the to make sure that whenever it reaches a state where it requires to be reset, the countdown behavior will switch to the opposite state it had previously. There is only one tweak left in the controller method that handles the countdown:

private tick() {
  if(!this.isPaused) {
    this.buttonLabel = 'Pause';
    if(--this.seconds < 0) {
      this.seconds = 59;
      if(--this.minutes < 0) {
        this.reset();
      }
    }
  }
}

Obviously, we do not want the countdown to continue when the timer is supposed to be paused, so we wrap the whole script in a conditional. In addition to this, we will want to display a different text on our button whenever the countdown is not paused and once again when the countdown reaches its end; stopping and then resetting the Pomodoro to its initial values will be the expected behavior. This reinforces the need of invoking the togglePause function within resetPomodoro.

Improving the data output

So far, we have reloaded the browser and played around with the newly created toggle feature. However, there is apparently something that still requires some polishing: when the seconds counter is less than 10, it displays a single-digit number instead of the usual two-digit numbers we are used to seeing in digital clocks and watches. Luckily, Angular implements a set of declarative helpers that format the data output in our templates. We call them pipes, and we will cover them in detail later in Chapter 4, Implementing Properties and Events in Our Components. For the time being, let's just introduce the number pipe in our component template and configure it to format the seconds output to display two digits all the time. Update our template so that it looks like this:

@Component({
  selector: 'timer',
  template: `
    <h1>{{ minutes }}: {{ seconds | number: '2.0' }}</h1>
    <p>
      <button (click)="togglePause()">{{ buttonLabel }}</button>
    </p>
  `
})

Basically, we appended the pipe name to the interpolated binding in our template separated by a pipe (|) symbol, hence the name. Reload the template and you will see how the seconds figure always displays two digits, regardless of the value it assumes.

We have created a fully functional Pomodoro timer widget that we can reuse or embed in more complex applications. Chapter 6, Building an Application with Angular Components, will guide us through the process of embedding and nesting our components in the context of larger component trees.

In the meantime, let's add some UI beautification to make our component more appealing. We already introduced a class attribute in our button tag as an anticipation of the implementation of the Bootstrap CSS framework in our project. Let's import the actual style sheet we downloaded through npm when installing the project dependencies. Open timer.html and add this snippet at the end of the <head> element:

<link href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/CSS/bootstrap.min.CSS" rel="stylesheet" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">

Now, let's beautify our UI by inserting a nice page header right before our component:

<body>
  <nav class="navbar navbar-default navbar-static-top">
    <div class="container">
      <div class="navbar-header">
        <strong class="navbar-brand">My Timer</strong>
      </div>
    </div>
  </nav>
</body>

Tweaking the component button with a Bootstrap button class will give it more personality and wrapping the whole template in a centering container will definitely compound up the UI. So let's update the template in our template to look like this:

<div class="text-center">
  <img src="assets/img/timer.png" alt="Timer">
  <h1> {{ minutes }}:{{ seconds | number:'2.0' }}</h1>
  <p>
    <button class="btn btn-danger" (click)="togglePause()">{{ buttonLabel }}</button>
  </p>
</div>
 

Summary


We looked at web components according to modern web standards and how Angular components provide an easy and straightforward API to build our own components. We covered TypeScript and some basic traits of its syntax as a preparation for Chapter 3, Introducing TypeScript. We saw how to set up our working space and where to go to find the dependencies we need to bring TypeScript into the game and use the Angular library in our projects, going through the role of each dependency in our application.

Our first component taught us the basics of creating a component and also allowed us to get more familiar with another important concept, Angular modules, and also how to bootstrap the application. Our second component gave us the opportunity to discuss the form of a controller class containing property fields, constructors, and utility functions, and why metadata annotations are so important in the context of Angular applications to define how our component will integrate itself in the HTML environment where it will live. Our first web component features its own template and such templates host property bindings declaratively in the form of variable interpolations, conveniently formatted by pipes. Binding event listeners is now easier than ever and its syntax is standards-compliant.

The next chapter will cover, in detail, all the TypeScript features we need to know to get up to speed with Angular in no time.

 

About the Authors

  • Christoffer Noring

    Christoffer Noring is a speaker at conferences as well as a guest lecturer at universities such as Imperial College. He has worked for several different industries as both a backend and frontend developer and currently works for McKinsey as a consultant. He is a co-organizer of the Angular conference ngVikings and a meetup organizer of more than 3000+ people. In his spare time, he enjoys cooking, painting, and spending time with his wife Sara.

    Browse publications by this author
  • Pablo Deeleman

    Pablo Deeleman is a former UI/UX designer who fell in love with JavaScript and CSS back in 1998, during the good old days of Netscape Navigator and Microsoft Internet Explorer 3. The discovery of Node.js back in 2011 became a turning point in his career, from which he decided to embrace full-time JavaScript-driven development, carving out a career as a JavaScript full stack engineer with special focus on single-page application development.

    With sound expertise in libraries and frameworks, such as Backbone.js, Knockout.js, Polymer, React, AngularJs, and Angular, Pablo built his career in a wide range of companies encompassing internationally acclaimed tube sites, fintech start-ups, and award-winning gaming and gambling sites. He currently works as a senior frontend engineer and Angular specialist for Red Hat, the multinational company that provides open source software products to the enterprise community.

    He is a Unity and Unreal expert. Among many projects, he has developed Gea2 (Sapienza) and Sticker Book (Dataware Games), and has consulted for Prosperity – Italy 1434 (Entertainment Game Apps, Inc) and Projekt I.D (RMIT).

    He is an active writer on game development, authoring Getting Started with Unity 5.x 2D Game Development, Unity UI Cookbook, and many other books. Finally, Francesco loves math, philosophy, logic, puzzle solving, and, most importantly, creating video games. Pablo has also authored Learning Angular 2 (Packt Publishing, 2016) and currently lives in sunny and bustling Barcelona, where he fulfills his other great passion: playing piano.

    Browse publications by this author

Latest Reviews

(10 reviews total)
Fairly good introduction to Angular
Hi, VGood book for reference
Toller Themenüberblick mit Tiefgang

Recommended For You

Angular Projects

Understand Angular web development by building real-world captivating applications exploring various web technologies and best practices

By Zama Khan Mohammed
Angular 6 by Example - Third Edition

Harness the power of Angular Components, Router, Forms, Directives and much more to build professional-grade web apps with TypeScript

By Chandermani Arora and 1 more
The JavaScript Workshop

Cut through the noise and get real results with a step-by-step approach to beginner JavaScript development

By Joseph Labrecque and 7 more
Docker on Windows - Second Edition

Learn how to run new and old applications in Docker containers on Windows - modernizing the architecture, improving security and maximizing efficiency.

By Elton Stoneman