Page 68 - MSDN Magazine, September 2017
P. 68
The SpeakerService looks like pretty much any other TypeScript class, with the sole exception of the @Injectable decorator on it—this is what will tell Angular that the SpeakerService can be dependency injected into those components that want to use it. The rest of the implementation is pretty straightforward. Right now, everything is working off of a constant array of Speaker instances held as a “private global” inside the speaker.service.ts file, called “SPEAKERS,” shown in Figure 2.
In effect, this array of three elements is your database, at least for the moment. When I talk about how to use Angular to send and receive HTTP requests, this array will be populated from JSON
Figure 1 Implementing the SpeakerService
returned to use from the server’s API implementation, and any changes you make will be to the array first. But for now, just hold it as a constant array.
Notice that the Upvote component is used directly inside the Speaker instances—this will allow the UpvoteComponent to build around the Upvote instances, and essentially preserve the whole MVC approach even at a fractal level inside models. Spiffy.
Using SpeakerService
The UI currently isn’t much to speak of (pun intended), but let’s look at how to make use of the service anyway. Assume that the homepage simply wants to grab the first Speaker out of the Speaker- Service (using the getSpeaker call with a parameter of “0”) and then extract the Upvote out of it for use in the UpvoteComponent on that page. Practically speaking, that means that the app.component file will need to get a reference to a SpeakerService, use that to obtain a Speaker, and then get a reference to the Upvote out of the Speaker and pass that to the UpvoteComponent. The latter part is pretty easy—you just modify the app.component.html template to reference an AppComponent field called speaker, from which you’ll get the Upvote instance, like so:
<h1> {{title}}
</h1>
<app-upvote votes="{{speaker.votes}}"><b>Current Upvotes:</b></app-upvote>
This is because Angular needs one more bit of glue in order to do the @Injectable magic. It needs to know that the code in this file is actually something that it’s supposed to know about.
So far, so good. But this means that you need a local speaker field inside the AppComponent, and that’s where you’ll also use the SpeakerService, as shown in Figure 3.
Wow, this Angular stuff is actually pretty easy. Save everything, do an “ng serve” and ... blank screen. What gives?
Providing SpeakerServices
Opening up the developer tools console in your browser yields a hint: At the top of the stack trace Angular says “No provider for SpeakerService!” in a rather loud voice. This is because Angular needs one more bit of glue in order to do the @Injectable magic. It needs to know that the code in this file is actually something that it’s supposed to know about. By default, Angular doesn’t just assume every .ts file in the directory is part of the application, so you need to set up a “provider” for the SpeakerService. This is done in the
import { Injectable } from '@angular/core';
import { Speaker } from './speaker'; import { Upvote } from './upvote';
@Injectable()
export class SpeakerService {
constructor() { }
getSpeakers() : Array<Speaker> {
return SPEAKERS; }
getSpeaker(id: number) : Speaker {
return SPEAKERS.find(speaker => speaker.id === id);
} }
Figure 2 The Constant Array of Speaker Instances
const SPEAKERS : Array<Speaker> = [ {
id: 0,
firstName: "Ted", lastName: "Neward", votes: new Upvote(30)
}, {
id: 1,
firstName: "Rachel", lastName: "Appel", votes: new Upvote(35)
}, {
id: 2,
firstName: "Nick", lastName: "Landry", votes: new Upvote(3)
}, ];
Figure 3 Using the SpeakerService
import { Component } from '@angular/core';
import { Speaker } from './speaker';
import { SpeakerService } from './speaker.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html', styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'SpeakerApp'; speaker: Speaker;
constructor(private speakerSvc: SpeakerService) {
this.speaker = this.speakerSvc.getSpeaker(0); }
}
60 msdn magazine
The Working Programmer