Book Image

Mastering Angular Components - Second Edition

By : Gion Kunz
Book Image

Mastering Angular Components - Second Edition

By: Gion Kunz

Overview of this book

Mastering Angular Components will help you learn how to invent, build, and manage shared and reusable components for your web projects. Angular components are an integral part of any Angular app and are responsible for performing specific tasks in controlling the user interface. Complete with detailed explanations of essential concepts and practical examples, the book begins by helping you build basic layout components, along with developing a fully functional task-management application using Angular. You’ll then learn how to create layout components and build clean data and state architecture for your application. The book will even help you understand component-based routing and create components that render Scalable Vector Graphics (SVG). Toward the concluding chapters, you’ll be able to visualize data using the third-party library Chartist and create a plugin architecture using Angular components. By the end of this book, you will have mastered the component-based architecture in Angular and have the skills you need to build modern and clean user interfaces.
Table of Contents (12 chapters)

Your first component

Keeping up the tradition, before we start building a real application together, we should write our first hello world component with Angular:

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

@Component({
selector: 'hello-world',
template: '<div>Hello {{name}}</div>'
})
class HelloWorldComponent {
name: string = 'World';
}

This is already a fully-working Angular component. We used ECMAScript 6 classes to create the necessary encapsulation required for a component. You can also see a meta-annotation that is used to declaratively configure our component. This statement, which looks like a function call that is prefixed with an at symbol, actually comes from the ECMAScript 7 decorator proposal. For the moment, you can think of decorators as a way to attach metadata to our component class.

ECMAScript 7 decorators are still very experimental at the time of writing this book. We're using TypeScript in the examples of this book, which is already implementing the decorator proposal with a slight twist. The Angular core team has decided to go with this experimental technology, since it reduces the overall amount of code and introduces an aspect oriented flavor to the Angular API.

It's important to understand that an element can only be bound to one single component. As a component always comes with a view, there is no way that we can bind more than one component to an element. On the other hand, an element can be bound to many directives, as directives don't come with a view—they only attach behavior.

In the Component decorator, we need to configure everything that is relevant to describe our component for Angular. This, of course, also includes our template for the view. In the preceding example, we are specifying our template directly within JavaScript as a string. We can also use the templateUrl property to specify a URL where the template should be loaded from.

The second configuration, applied using the selector property, allows us to specify a CSS selector, which is used by Angular to attach the component to certain elements within our view. Every time Angular encounters an element which matches the component's selector, it will render the given component into that element.

Now, let's enhance our example a little bit so that we can see how we can compose our application from smaller components:

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

@Component({
selector: 'shout-out',
template: '<strong>{{words}}</strong>'
})
class ShoutOutComponent {
@Input() words: string;
}

@Component({
selector: 'hello-world'
template: '<shout-out words="Hello, {{name}}!"></shout-out>'
})
class HelloWorldComponent {
name: string = 'World';
}

You can see that we have now created a small component that allows us to shout out words as we like. In our Hello World application, we make use of this component to shout out Hello, World!

Within the template of our hello world component, we are including the shouting component by placing an HTML element which matches the CSS element selector of the shouting component.

Over the course of this book and while writing our task management application, we will learn a lot more about the configuration and implementation of components. However, before we start with this in the Chapter 2, Ready, Set, Go!, we should take a look at some tools and language features that we'll use during this book.

Angular NgModule

Organizing an application solely by composing components comes with some challenges. Angular supports the concept of application modules, which essentially are just containers around components that help structure your application.

The concept of NgModule was introduced to mainly solve the following issues:

  • Explicit template parsing:
    With the use of modules and by declaring all components, directives, pipes, and providers which are used inside of your application module, Angular is able to parse HTML templates very explicitly. This is really helpful when it comes to debugging. Let's say you're including an element within one of your component templates which does not match any of the selectors specified by the components within your module. Angular can now assert an error because you explicitly told it what components are available within your module. Without telling Angular which components belong to your application module, it would not be able to know if you're including a non-existing component within your template.
  • Simpler dependency resolution:
    Since Angular can now simply resolve your main application module to find out what components are present within your application, things get simplified a lot. Imagine you have a very complex application existing of hundreds of components. Without modules, Angular would need to follow each individual component to find out how they are dependent on each other. With modules, Angular can simply check what components are declared inside of the module to find all components.
  • Lazy loading with the Angular router:
    The router of Angular is able to load parts of your application lazily when required. This is a very powerful feature, but it requires that you declare a bundle of application artefacts like components or directives, to be loaded asynchronously after your main application has started. NgModule comes in very handy at this point. By creating a separate module using NgModule, you can now define a part of your application consisting of new components and other artefacts. Within the build of your application, this module is then built separately into its own JavaScript resource, which can be loaded asynchronously at runtime by the router.

Your application requires at least one main module, which is declaring all your application components. Let's look at a very simple example and build the main module for our HelloWorld component:

import {BrowserModule} from '@angular/platform-browser';
import {NgModule} from '@angular/core';
import {HelloWorldComponent} from './hello-world.component';
import {ShoutOutComponent} from './shout-out.component';

@NgModule({
declarations: [HelloWorldComponent, ShoutOutComponent],
imports: [BrowserModule],
bootstrap: [HelloWorldComponent]
})
export class HelloWorldAppModule { }

Similar to a component definition, we're using an ES6 class and a decorator to define an Angular module. The NgModule decorator of our main application module has three configuration properties:

A module dependency tree: Module A importing module B and C so that all components are available to module A

The declarations property is used to tell Angular what components, directives, and pipes are present within this module. If our application consists of 30 components, we need to add them all to the declarations of the NgModule. Every time you create a new component, you will also need to add it to the declarations array within your application module.

Within the array of the imports property, we can tell Angular to import other NgModule. This way, you can compose your application modules from many smaller modules if you like. However, there's no real benefit of structuring your application into submodules, unless you're exporting a submodule as a library, or if you're using the lazy loading feature of the router, as discussed earlier. It's crucial that you always import the Angular BrowserModule within your main application module. The BrowserModule contains all the Angular core components, directives, and other dependencies which are required in order to run your application within a browser environment.

Finally, the bootstrap property is telling Angular which of your components should be rendered first. You should specify your main application component here, which is representing the root component of your application. In the second chapter of this book, we'll take a closer look at the bootstrapping mechanism of Angular.