Get started with Angular: The InfoWorld tutorial

A step-by-step guide to installing the tools, creating an application, and getting up to speed with Angular components, directives, services, and routers

1 2 Page 2
Page 2 of 2

Note that Visual Studio Code installs a private copy of TypeScript for itself, while Angular installs a global copy of TypeScript. These aren’t always the same version, but it shouldn’t matter. If Visual Studio Code starts bleating about this, you can click on the button that essentially says, “Don’t bother me about this again” and it’ll change its options. If you want the version check reinstated at any time, go to Code > Preferences > Settings and change the value next to “typescript.check.tscVersion" from false to true.

Explore the Angular source code

Now that you finally have a working Angular “Hello” project open in an editor, you can start exploring the source code. Actually, let’s go back to the documentation first and look at the setup guide to see the explanations. There are boxes about halfway down the page, which show the three Angular core source files:

Angular fig07 core src files IDG

You’ve seen app.component.ts before, in the online QuickStart. As the page says, “it is the root component of what will become a tree of nested components as the application evolves.” The next file over, app.module.ts, defines “the root module that tells Angular how to assemble the application. Right now it declares only the AppComponent. Soon there will be more components to declare.”

The third file, main.ts, is deceptively simple:

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

platformBrowserDynamic().bootstrapModule(AppModule);

platformBrowserDynamic is the Angular JIT compiler, and bootstrapModule is the function that kicks off the app. Yes, Angular has its own just-in-time compiler, which knows how to turn Angular directives into executable JavaScript. Let’s not get into Angular’s other compilers at this point. I told you earlier not to worry about how the decorator function and interpolation binding are implemented. Now you know: Angular supplies its own compilers that turn all the declarations into code. If you go back to Visual Studio Code and open src/main.ts, you’ll find essentially the same contents (modulo whitespace) if you used the QuickStart seed. You’ll find a longer, more complicated version of the bootstrap file if you generated the app from the Angular CLI, which hints at the different compilers and environments available for Angular:

Angular fig09 my app main ts IDG

What’s going on here? You see an environment with a variable called production, and a setter function called enableProdMode. There’s an explanation in the source code found in environment/environments.ts in the CLI-generated app:

Angular fig10 environments IDG

Angular architecture

As I planned this tutorial, I considered sending you to the official Angular architecture documentation to learn what they had to say about their own architecture; however, I didn’t want any damage to your mental health on my conscience. You’re free to go look at that, but you may want a stiff drink first.

More seriously, the problem with Angular is not the architecture itself, but rather that the terminology is overloaded with JavaScript and TypeScript terminology. JavaScript (more accurately CommonJS and TypeScript) and Angular both have modules, but they are different. JavaScript and Angular both have libraries, but again they are different. Both have imports and exports, and, as you’ve probably guessed, they are different. Have you reached for the bottle yet? How about the headache pills?

Angular, as I mentioned earlier, adds decorators, directives, and components to JavaScript and TypeScript. Because none of these are native facilities, Angular has its own compiler to turn them into JavaScript, which you launch, and then have the compiler bootstrap your app. Meanwhile, TypeScript also has a compiler, more accurately a transpiler, which generates JavaScript.

OK. Take a deep breath. Let’s look at the Angular architecture diagram.

Angular fig11 architecture IDG

What are you seeing here? Basically, the diagram shows the relationships between some of the major building blocks of Angular: modules, components, templates, metadata, data binding, directives, services, and dependency injection. There are additional optional building blocks in Angular, such as the router module.

For this tutorial, I’m going to concentrate on the four building blocks that you’ll need on a daily basis: components, directives, services, and routers. If you feel the need to understand Angular modules right this minute, by all means go read the documentation and then come back. If not, stay with me.

Components

Let’s look again at app.components.ts, which is the root component of an Angular app. For a generated seed app, it’s the only component.

Angular fig12 my app ts app component IDG

If you’re trying to create an app that uses protocols other than HTTP, Tornado has you covered.

There are several ways to think about Angular components. One is that they are TypeScript classes, as seen at line 8 above. Note that classes are exported in TypeScript. Since by convention Angular components are in separate files, TypeScript needs to know that you intend them to be visible to other components.

No other component actually needs to import the base class, but we export it anyway as a matter of consistency.

export class AppComponent {
title = 'app works!';
}

Another way to think about components is that they each control a patch of screen called a view, which starts to make sense when an app has many components for specialized views, such as a top bar, a side navigation bar, a side toolbar, and a tabbed detail view. All those view components together could describe Visual Studio Code if it were an Angular app. (It’s not.) A third way to look at Angular view components is as the container for all the metadata that ties the view together, expressed as a @Component directive. The root component shown above defines three metadata properties:

selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']

The selector defines the mapping from an Angular view to the DOM (Document Object Model), and says to display the view inside the (custom) <app-root> tag in index.html:

<body>
   <app-root>Loading...</app-root>
</body>

In Angular you don’t mess with HTML selectors from your code, as you would in jQuery. Instead you set properties and values in the component class. The data binding automatically reflects them to the DOM.

The templateUrl property defines the name and location of the Angular template file for the view. The template combines HTML markup with Angular template syntax, as shown by the HTML tags and the handlebar notation below:

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

As you have probably guessed, this template says to display the AppComponent class title property as a level-1 head. You saw “app works!” in a basic H1 style when you ran the app earlier. This could also have been done with an embedded template property and string; separating the template out into its own file using the templateURL property helps with maintainability and is more convenient for templates of nontrivial size. (I was going to say rodents — I mean templates — of unusual size, but in fact Angular templates are usually bigger than you’d want to stuff onto one line.)

The styleUrls property holds an array of CSS file names and locations to define the styles that apply to the view. It needs to be an array because CSS styles are hierarchical. As it happens, the default app.component.css file in a generated seed app is empty, which is why we saw a basic H1 style and not something better styled. Later in the Angular CLI quick start tutorial, you change the title text and set the CSS to:

h1 {
color: #369;
font-family: Arial, Helvetica, sans-serif;
font-size: 250%;
}

That gives you the same look as the seed project, which also has title text of “Hello Angular.”

Angular fig05 hello angular IDG

Directives

The Angular @Component I’ve been describing is a special kind of directive. Angular renders templates according to the instructions given by directives, and dynamically transforms the DOM. There are two other kinds of directives besides components: structural and attribute directives.

Structural directives alter layout by adding, removing, and replacing elements in the DOM. Attribute directives alter the appearance or behavior of an existing element. In templates they look like regular HTML attributes, hence the name. Let’s look at some examples from the Angular documentation. The first example, from the Hero List template, includes two built-in structural directives.

<li *ngFor="let hero of heroes"></li>

<hero-detail *ngIf=“selectedHero"></hero-detail>

The top example, *ngFor written inside list tags, generates one list item for every hero in the heroes list. This is a very concise, expressive way to create a list based on data; Angular’s JIT compiler turns it into efficient JavaScript and HTML.

The second example, *ngIf written inside a custom hero-detail tag, displays a hero-detail record only if one has been selected from the heroes list and the selected detail record exists. Together with the *ngFor directive, this efficiently implements a master-detail application.

For the full context, consider the entire Hero List template:

<h2>Hero List</h2>
<p><i>Pick a hero from the list</i></p>
<ul>
<li *ngFor="let hero of heroes" (click)="selectHero(hero)">
{{hero.name}}
</li>
</ul>
<hero-detail *ngIf="selectedHero" [hero]="selectedHero"></hero-detail>

The ngModel directive, which implements two-way data binding, is an example of an attribute directive. ngModel modifies the behavior of an existing element (typically an <input> tag) by setting its display value property and responding to change events. Here’s how the hero-detail component uses ngModel to handle changes:

<input [(ngModel)]=“hero.name">

The magic here is that Angular not only sets the initial value of the input field, it takes care of updating the model in response to change events, without making you write event handler code. Much of the routine work in developing Angular applications involves writing custom components. You can also write custom structural and attribute directives when and if you need them.

Services

When I described the Hero List above, I glossed over how the component gets its list of heroes. In fact, it uses a service provider that implements that functionality. Sure, the component could technically implement everything itself, but the preferred style for Angular applications is to keep components focused on the view and the model, with all the back-end work consumed as services.

Service is a broad category in Angular that includes any value, function, or feature that your application needs. The HeroService is an exported class that maintains an internal list of heroes, which it gets from a BackendService that implements a getAll method:

export class HeroService {
private heroes: Hero[] = [];

constructor(
private backend: BackendService,
private logger: Logger) { }
getHeroes() {
this.backend.getAll(Hero).then( (heroes: Hero[]) => {
this.logger.log('Fetched ${heroes.length} heroes.');
this.heroes.push(...heroes); // fill cache
});
return this.heroes;
}
}

How does the HeroService know how to use the BackendService and the Logger? In the root module, preferentially, these and any other services are listed as providers:

providers: [
BackendService,
HeroService,
Logger
],

You can also register a service at the component level in the providers property of the @Component metadata:

@Component({
moduleId: module.id,
selector: 'hero-list',
templateUrl: './hero-list.component.html',
providers: [ HeroService ]
})

The preference for registering services in the root module is driven by wanting all components to use the same instance of the services. You might want to register a service at the component level to keep all the pieces of the component together, for modularity, or to give each instance of the component its own instance of a service.

A component lists the services it needs in its constructor:

constructor(private service: HeroService) { }

When Angular creates a component, it first asks an injector for the services that the component requires. The injector keeps all its service instances in a container. At component instantiation time, Angular calls the injector, gets the service instances, and then calls the component’s constructor with the instances as arguments. That, in a nutshell, is dependency injection, which is one way to accomplish inversion of control.

Routers

I mentioned earlier that Angular applications usually contain multiple view components. Once you have more than one view, you need a way to navigate from one view to another. For that Angular has routers, implemented in an external, optional Angular NgModule called RouterModule. The router is a combination of multiple provided services (RouterModule), multiple directives (RouterOutlet, RouterLink, RouterLinkActive), and a configuration (Routes).

Why not just switch from view to view using HTML links? The basic reason is that links cause a new page to load, and Angular by preference creates single-page applications (SPAs), which appear smoother to the user.

Routing in a single-page app, whether it’s an application based on Angular or another technology such as Ruby on Rails, can get complicated fairly quickly. You want to preserve the idea of a mapping between a URL and an application state without incurring the time overhead of a complete page reload after every HTTP request.

In Angular, that requires a number of conditions to be met. First, the base HREF must be set explicitly:

<head>
<base href=“/">

Next, you need to map routes between paths and components:

import { RouterModule } from '@angular/router';
RouterModule.forRoot([
{
path: ‘heroes',
component: HeroesComponent
}
])

There’s only one path here now, but there will be more.

Third, you need to add that to the AppModule imports array.

Fourth, you need to set router links and outlets, to emulate what happens with an HTML link:

template: '
<h1>{{title}}</h1>
<a routerLink=“/heroes">Heroes</a>
<router-outlet></router-outlet>
'

Finally, you want to redirect the null path to our link:

{
path: '',
redirectTo: ‘/heroes',
pathMatch: ‘full'
},

If you follow the full Tour of Heroes tutorial, you’ll see that it adds a dashboard view and sets the redirectTo to point to /dashboard, which causes the routing to actually make sense. In fact, at this point, I believe that following the full tutorial is exactly the right thing to do. You are ready to take it on. Have fun!

Copyright © 2017 IDG Communications, Inc.

1 2 Page 2
Page 2 of 2