Angular 5 Quickstart. Part 2: Classes and Directives

We continue yesterday’s Angular 5 quickstart by building on top of our small JavaScript Trivia app.

We looked at components and modules and left the application in a pretty stable state, displaying one piece of trivia as per below.

plunkr2

But functionality-wise, clearly this isn’t a very exciting app. Yet. Next on our agenda is displaying a list of trivia items instead of just the one, and making our <trivia> component truly reusable.

Let’s start by updating our TriviaComponent class by adding some properties. Amend your src/app.ts to include the below:

class TriviaComponent {
  question: string;
  answer: string;
}

And here’s how it should look in its entirenty:

import { Component } from '@angular/core';
import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

@Component({
  selector: 'trivia',
  template: `
    <h1>How many JavaScript scopes?</h1>
    <p>Two. Global and Local.</p>
  `
})

class TriviaComponent {
  question: string;
  answer: string;
}

@NgModule({
  imports: [BrowserModule],
  declarations: [TriviaComponent],
  bootstrap: [TriviaComponent]
})
export class AppModule {
}

Great stuff! Now, what we did before was to take advantage of TypeScript’s typed properties, and specified that an object of class TriviaComponent will have two properties question and answer, both of type string. If we put anything but strings in these properties, TypeScript will throw an error.

Classes

At the moment we aren’t taking advantage of all that the TriviaComponent class has to offer. Our trivia data is just hardcoded as part of our component’s template string, and that offers little to no flexibility. What we want is to store that data in objects of class TriviaComponent, which we can create and loop through at will.

TypeScript classes use a special type of function, called constructor, which is called every time an instance of that class is created. Let’s add a constructor to our TriviaComponent class.

class TriviaComponent {
  question: string;
  answer: string;
 
  constructor() {
    this.question = "How many JavaScript scopes?";
    this.answer = "Two. Global and Local.";
  }
}

String interpolation

We also want to update the @Component template with references to TriviaComponent instance properties instead of hardcoded strings.

We do this in the template by using what is called moustache syntax, and looks like this: {{ }}. Everything contained between the double curly brackets is considered JavaScript code, run by Angular and then added to the HTML. Therefore, we can write something like this:

@Component({
  selector: 'trivia',
  template: `
    <h1>{{question}}</h1>
    <p>{{answer}}</p>
  `
})

The application still works as before, but we are on our way to making it fully flexible.

Loops

We now want to display a list of trivia instead of just one. For this we’ll be creating another component, TriviaListComponent, as per below:

@Component({
  selector: 'trivia-list',
  template: `
<div *ngFor="let trivia of trivias">
  <h1>{{trivia.question}}</h1>
  <p>{{trivia.answer}}</p>
</div>
  `
})
class TriviaListComponent {
  trivias: Object[];

  constructor() {
    this.trivias = [
      {
        question: "How many JavaScript scopes?",
        answer: "Two. Global and Local."
      },
      {
        question: "What's a JavaScript closure?",
        answer: "An inner function with access to the outer function's variables—scope chain."
      },
    ];
  }
}

This component should look very familiar, as it’s in fact very similar to our TriviaComponent from before. It has a @Component decorator, and a class with a constructor. It only has one property trivias, of type array of Object elements, and that gets set in its constructor.

What’s interesting here is how we’ve defined its template. We used a special syntax called NgFor on the div element:

<div *ngFor="let trivia of trivias">

*ngFor="let trivia of trivias" creates a new HTML element, using the div element it’s attached to as a template, for every trivia in the trivias array, making the current element in the trivias array available to a trivia. We are therefore able to access its properties inside the loop via {{trivia.question}} and {{trivia.answer}}.

It will also make available to the element a variable called joke which is he item in the joke array it’s currently looping over.

Now, in order to use our TriviaListComponent we need to add it to the declarations on our NgModule and also set it up as the component we want to bootstrap the page with. This is similar to what we did with TriviaComponent previously.

Let’s update @NgModule:

@NgModule({
  imports: [BrowserModule],
  declarations: [TriviaComponent, TriviaListComponent],
  bootstrap: [TriviaListComponent]
})

Also, in index.html we want to add our <trivia-list> tag, since we are now bootstrapping TriviaListComponent and that’s its selector:

<body>
    <trivia-list>
    loading...
    </trivia-list>
</body>

plunkr3.png

Our app now displays a list of trivias, which is pretty awesome! We’ll continue developing this in the future, but in the meantime, make sure you check part 1 of this tutorial if you haven’t already, and as always, happy coding!