Page 66 - MSDN Magazine, September 2017
P. 66
The Working Programmer TED NEWARD How To Be MEAN: Servicing Angular
Welcome back again, MEANers.
One of the common needs of an Angular application is to
obtain or update data from locations not inside the browser—which is usually everywhere. Most often, an Angular app will need to exchange data (usually in the form of JSON packets) with an HTTP- based API implementation somewhere on the Internet.
Unfortunately, this doesn’t really “fit” well with the notion of a component. Multiple components will often need to communi- cate with the same server through the same API implementation, and to duplicate that code in each and every component would get ugly. Certainly, as you’ve seen with the Upvote component (msdn.com/magazine/mt784667), it’s possible to create a standalone TypeScript class and simply make use of that—essentially bringing the concept of “library module” into Angular. But as so frequently happens, the Angular team anticipated this need, and has given unto us ... services.
A service, in Angular terms, is an injectable module: “module” because you’ll create a TypeScript module that encapsulates the service’s implementation, and “injectable” because through the use of some decorators, you’ll make the service known to Angular, so that those components that wish to use it simply have to declare it as a parameter (similar to how the @Input/@Output decorators worked earlier) and lo, they will receive one.
(Take note: An Angular service is not implicitly in a 1-to-1 relationship with an “API service” or “microservice” or any of the other overloaded uses of the term. If the term is still confusing, remember that an Angular service is simply a TypeScript mod- ule whose users are always other Angular components—humans never interact with an Angular service directly.)
Let’s have a look.
SpeakerService
The start of every service will typically begin with asking the Angular CLI to create the basic scaffolding for you, so let’s start with that: From a command prompt, type “ng generate service Speaker.” This will generate two files—speaker.service.ts and speaker.service.spec.ts—and inside of them will be the basic outline for the SpeakerService class (the “Service” is an assumed- desired suffix to the name specified on the command-line) and the testing code, respectively.
However, as of this moment, you don’t have a Speaker type to be returned from the service! (As legendary cartoon character Homer Simpson would say ... “D’oh!”) Again, this is easily fixed by asking
the CLI to create a Speaker type to use: “ng generate class Speaker.” This time, the CLI will generate a single file, speaker.ts, which con- tains only the class Speaker. This is important to notice: The CLI is looking to enforce Angular conventions by automatically putting the appropriate suffix on the various types being generated. There’s a com- mand-line parameter to control the naming, but, frankly, just go with the defaults here—it will make many things much easier over time.
Speaker
I’m going to keep the Speaker type pretty straightforward for now. Obviously, this could get as large and as complicated as necessary, but it wouldn’t teach you anything about Angular to do it that way. The Speakers have some simple properties, and you’re going to take the simple (perhaps naïve) perspective that an evaluation is of the speaker, and not of the talk. Were this a production application, you’d probably have a “Speakers HAVE-MANY Talks” relationship and then “Talks HAVE-MANY Upvotes” relationship, but, again, that doesn’t really show off Angular. So Speaker looks like this:
import { Upvote } from './upvote';
export class Speaker { id: number; firstName: string; lastName: string; votes: Upvote;
}
A service, in Angular terms, is an injectable module.
It’s a simple class, enough so that I’m going to skip showing the tests for it. (Note that if you go looking for the speaker.spec.ts file, it doesn’t exist—by default, the CLI doesn’t generate a test file for a simple class like this. If you want a test file—and you really, really should want one—then you should pass “—spec true” on the command line when doing the ng generate command.)
SpeakerService
Now that you have a type to represent speakers, you can build out a service that will basically act as a repository (meaning, following the basic concept of the Repository pattern) for speaker instances. For the moment, this will live in memory, and its (so far, read-only) implementation should be fairly clear, as you can see in Figure 1.
58 msdn magazine