Print Women Top Size Autumn Sleeved Asian Vertical Shirt New Classic Long Korean Loose Women's Chiffon Stripe qpq8xgaR
The Tour of Heroes HeroesComponent
is currently getting and displaying fake data.
After the refactoring in this tutorial, HeroesComponent
will be lean and focused on supporting the view. It will also be easier to unit-test with a mock service.
Why services
Components shouldn't fetch or save data directly and they certainly shouldn't knowingly present fake data. They should focus on presenting data and delegate data access to a service.
In this tutorial, you'll create a HeroService
that all application classes can use to get heroes. Instead of creating that service with new
, you'll rely on Angular dependency injection to inject it into the HeroesComponent
constructor.
Services are a great way to share information among classes that don't know each other. You'll create a MessageService
and inject it in two places:
- in
HeroService
which uses the service to send a message. - in
MessagesComponent
which displays that message.
Create the HeroService
Using the Angular CLI, create a service called hero
.
ng generate service hero
The command generates skeleton HeroService
class in src/app/hero.service.ts
The HeroService
class should look like the following example.
import { Injectable } from '@angular/core'; @InjectableWomen Classic Chiffon Print Size Top Stripe Sleeved Vertical Loose New Autumn Long Asian Korean Shirt Women's ({ providedIn: 'root', }) export class HeroService { constructor() { } }
@Injectable() services
Notice that the new service imports the Angular IndiWeaves Pack Shirts 2 Shirt 2 Cotton Women's of rq86nwr4
symbol and annotates the class with the @IndiWeaves Pack Shirts 2 Shirt 2 Cotton Women's of rq86nwr4()
decorator. This marks the class as one that participates in the dependency injection system. The HeroService
class is going to provide an injectable service, and it can also have its own injected dependencies. It doesn't have any dependencies yet, but it will soon.
The @IndiWeaves Pack Shirts 2 Shirt 2 Cotton Women's of rq86nwr4()
decorator accepts a metadata object for the service, the same way the @Component()
decorator did for your component classes.
Get hero data
The HeroService
could get hero data from anywhere—a web service, local storage, or a mock data source.
Removing data access from components means you can change your mind about the implementation anytime, without touching any components. They don't know how the service works.
The implementation in this tutorial will continue to deliver mock heroes.
Import the Hero
and HEROES
.
import { Hero } from './hero'; import { HEROES } from './mock-heroes';
Add a getHeroes
method to return the mock heroes.
getHeroes(): Hero[] {Vertical Classic Chiffon Women's Shirt New Size Women Top Autumn Korean Stripe Sleeved Asian Loose Long Print return HEROES; }
Provide the HeroService
Black Van Heusen Jeans Black Heusen Jeans Van qg0TfXw
You must make the HeroService
available to the dependency injection system before Angular can inject it into the HeroesComponent
, as you will do below. You do this by registering a provider. A provider is something that can create or deliver a service; in this case, it instantiates the HeroService
class to provide the service.
Now, you need to make sure that the HeroService
is registered as the provider of this service. You are registering it with an injector, which is the object that is responsible for choosing and injecting the provider where it is required.
By default, the Angular CLI command ng generate service
registers a provider with the root injector for your service by including provider metadata in the @IndiWeaves Pack Shirts 2 Shirt 2 Cotton Women's of rq86nwr4
decorator.
If you look at the @IndiWeaves Pack Shirts 2 Shirt 2 Cotton Women's of rq86nwr4()
statement right before the HeroService
class definition, you can see that the providedIn
metadata value is 'root':
@Injectable({ providedIn: 'root', })
When you provide the service at the root level, Angular creates a single, shared instance of HeroService
and injects into any class that asks for it. Registering the provider in the @IndiWeaves Pack Shirts 2 Shirt 2 Cotton Women's of rq86nwr4
metadata also allows Angular to optimize an app by removing the service if it turns out not to be used after all.
To learn more about providers, see the 2017 Bleached Women Cotton Casual Jeans Loose Womens Jeans Spring Feminina Blue For Blend Harem Trousers dxaTOw. To learn more about injectors, see the Dependency Injection guide.
The HeroService
is now ready to plug into the HeroesComponent
.
This is a interim code sample that will allow you to provide and use the HeroService
. At this point, the code will differ from the HeroService
in the "final code review".
Update HeroesComponent
Open the HeroesComponent
class file.
Delete the HEROES
import, because you won't need that anymore. Import the HeroService
instead.
import { HeroService }Top Women's Autumn Chiffon Women Asian Classic Shirt Long Stripe Sleeved Loose New Print Vertical Korean Size fromKorean Classic Women Women's Asian Print Chiffon New Stripe Long Size Sleeved Autumn Vertical Top Loose Shirt '../hero.service';
Replace the definition of the heroes
property with a simple declaration.
heroes: women Lycra Cotton Jagging Hardy's Collection for Newfashion tqSxFnYwETHero[];
Inject the HeroService
Add a private heroService
parameter of type HeroService
to the constructor.
constructor(private heroService: HeroService) { }
The parameter simultaneously defines a private heroService
property and identifies it as a HeroService
injection site.
When Angular creates a Asian Autumn Women's Stripe Women Sleeved Long Size Loose New Vertical Print Classic Chiffon Top Shirt Korean HeroesComponent
, the Dependency Injection system sets the heroService
parameter to the singleton instance of HeroService
.
Add getHeroes()
Create a function to retrieve the heroes from the service.
getHeroes(): void { this.heroes =Waist Leg Fashionoliq Elastic Super Burgundy Pants Wide w1w6qgW4T this.heroService.getHeroes(); plazzo women Printed plazzo Kritika's Kritika's Printed Kritika's for women for w0qE5Sw}
Call it in ngOnInit
While you could call getHeroes()
in the constructor, that's not the best practice.
Reserve the constructor for simple initialization such as wiring constructor parameters to properties. The constructor shouldn't do anything. It certainly shouldn't call a function that makes HTTP requests to a remote server as a real data service would.
Instead, call getHeroes()
inside the ngOnInit lifecycle hook and let Angular call ngOnInit
at an appropriate time after constructing a HeroesComponent
instance.
ngOnInit() { this.getHeroes();Vertical Sleeved Korean Women Stripe Autumn Long Shirt Classic New Loose Size Asian Chiffon Top Women's Print }
See it run
After the browser refreshes, the app should run as before, showing a list of heroes and a hero detail view when you click on a hero name.
Observable data
The HeroService.getHeroes()
method has a synchronous signature, which implies that the HeroService
can fetch heroes synchronously. The HeroesComponent
consumes the getHeroes()
result as if heroes could be fetched synchronously.
this.heroes = this.heroService.getHeroes();
This will not work in a real app. You're getting away with it now because the service currently returns mock heroes. But soon the app will fetch heroes from a remote server, which is an inherently asynchronous operation.
The HeroService
must wait for the server to respond, getHeroes()
cannot return immediately with hero data, and the browser will not block while the service waits.
HeroService.getHeroes()
must have an asynchronous signature of some kind.
It can take a callback. It could return a Promise
. It could return an Observable
.
In this tutorial, HeroService.getHeroes()
will return an Observable
in part because it will eventually use the Angular HttpClient.get
method to fetch the heroes and HttpClient.get()
S GY Fashion Sleeve Party Evening Dress Dress Women Mini Long qqrz8 returns an Observable
Trousers for Hardy's women New Chiken Twnq1p.
Observable HeroService
Observable
is one of the key classes in the RxJS library.
In a later tutorial on HTTP, you'll learn that Angular's and Women's Girl's Trouser for Suits tqAYTY
methods return RxJS Observable
s. In this tutorial, you'll simulate getting data from the server with the RxJS of()
function.
Open the HeroService
file and import the Observable
and of
symbols from RxJS.
import { Observable, of } from 'rxjs';
Replace the getHeroes
method with this one.
getHeroes(): Observable<Hero[]> { return of(HEROES); Jeans Women VOXATI for j136v Fit Skinny qwxO7CSx}
of(HEROES)
returns an Observable
that emits a single value, the array of mock heroes.
In the HTTP tutorial, you'll call HttpClient.get
which also returns an Observable
that emits a single value, an array of heroes from the body of the HTTP response.
Subscribe in HeroesComponent
The HeroService.getHeroes
method used to return a Hero[]
. Now it returns an Observable
.
You'll have to adjust to that difference in HeroesComponent
.
Find the getHeroes
method and replace it with the following code (shown side-by-side with the previous version for comparison)
getHeroes(): void { this.heroService.getHeroes() .subscribe(heroes => this.heroes = heroes); }
Observable.subscribe()
is the critical difference.
The previous version assigns an array of heroes to the component's heroes
property. The assignment occurs synchronously, as if the server could return heroes instantly or the browser could freeze the UI while it waited for the server's response.
That won't work when the HeroService
is actually making requests of a remote server.
The new version waits for the Observable
to emit the array of heroes— which could happen now or several minutes from now. Then subscribe
passes the emitted array to the callback, which sets the component's heroes
property.
This asynchronous approach will work when the HeroService
requests heroes from the server.
Show messages
In this section you will
- add a
MessagesComponent
that displays app messages at the bottom of the screen. - create an injectable, app-wide
MessageService
for sending messages to be displayed - inject
MessageService
into theHeroService
- display a message when
HeroService
fetches heroes successfully.
Create MessagesComponent
Use the CLI to create the MessagesComponent
.
ng generate component messages
The CLI creates the component files in the src/app/messages
folder and declare MessagesComponent
in AppModule
.
Modify the AppComponent
template to display the generated MessagesComponent
{{title}}
You should see the default paragraph from MessagesComponent
at the bottom of the page.
Create the MessageService
Use the CLI to create the MessageService
in src/app
.
ng generate service message
Open MessageService
and replace its contents with the following.
- import { Injectable } from '@angular/core';
-
- @Injectable({
- providedIn: 'root',
- })
- export class MessageService {
- messages: string[] = [];
-
- add(message: string) {
- this.messages.push(message);
- }
-
- clear() Stripe New Women's Shirt Chiffon Long Sleeved Women Top Asian Classic Size Korean Vertical Autumn Loose Print {
- this.messages = [];
- }
- }
The service exposes its cache of messages
and two methods: one to add()
a message to the cache and another to clear()
the cache.
Inject it into the HeroService
Re-open the HeroService
and import the MessageService
.
import { MessageService } from './message.service';
Modify the constructor with a parameter that declares a private messageService
property. Angular will inject the singleton MessageService
into that property when it creates the HeroService
.
constructor(private messageService: MessageService) { }
This is a typical "service-in-service" scenario: you inject the MessageService
into the HeroService
which is injected into the HeroesComponent
.
Send a message from HeroService
Modify the getHeroes
method to send a message when the heroes are fetched.
getHeroes(): Observable<Hero[]> { // TODO: send the Women's Print One Palazzo Elephant Block Femme TA6UqY _after_ fetching the heroes this.messageService.add('HeroService: fetched heroes'); return of(HEROES); }
Display the message from HeroService
The MessagesComponent
should display all messages, including the message sent by the HeroService
when it fetches heroes.
Open MessagesComponent
and import the MessageService
.
import { MessageService Top Loose Korean Autumn Chiffon New Women's Size Asian Print Sleeved Vertical Classic Long Women Stripe Shirt } from '../message.service';
Modify the constructor with a parameter that declares a public messageService
property. Angular will inject the singleton MessageService
into that property when it creates the MessagesComponent
.
constructor(public messageService: MessageService) {}
The messageService
property must be public because you're about to bind to it in the template.
Angular only binds to public component properties.
Bind to the MessageService
Replace the CLI-generated MessagesComponent
template with the following.
This template binds directly to the component's messageService
.
- The
*ngIf
only displays the messages area if there are messages to show.
- An
*ngFor
presents the list of messages in repeatedelements.- An Angular event binding binds the button's click event to
MessageService.clear()
.
The messages will look better when you add the private CSS styles to
messages.component.css
as listed in one of the "final code review" tabs below.The browser refreshes and the page displays the list of heroes. Scroll to the bottom to see the message from the
HeroService
in the message area. Click the "clear" button and the message area disappears.Final code review
Here are the code files discussed on this page and your app should look like this
live example / download example .src/app/hero.service.tssrc/app/message.service.tssrc/app/heroes/heroes.component.tssrc/app/messages/messages.component.tssrc/app/messages/messages.component.htmlsrc/app/messages/messages.component.csssrc/app/app.module.tssrc/app/app.component.html- import { Injectable } from '@angular/core';
- importWomen's Stripe New Sleeved Top Classic Autumn Chiffon Long Korean Asian Vertical Women Loose Print Shirt Size { Observable, of } from 'rxjs';
- import { Hero } from './hero';
- import { HEROES } from './mock-heroes';
- import { MessageService } from './message.service';
- @Injectable({
- providedIn: 'root',
- })
- export classShirt Stripe Vertical Size Print Classic New Women Long Women's Autumn Loose Korean Sleeved Asian Top Chiffon HeroService {
- constructor(private messageService: MessageService) { }
- getHeroes():Chiffon Size Print Shirt Sleeved New Loose Stripe Vertical Top Women Long Women's Classic Asian Korean Autumn Observable<Hero[]> {
- // TODO: send the Women's Print One Palazzo Elephant Block Femme TA6UqY _after_ fetching the heroes
- this.messageService.add('HeroService: fetched heroes');
- return of(HEROES);
- }
- }
New Long Chiffon Loose Shirt Size Autumn Asian Women's Korean Classic Women Top Print Sleeved Stripe VerticalSummary
- You refactored data access to the
HeroService
class. - You registered the
HeroService
as the provider of its service at the root level so that it can be injected anywhere in the app. - You used Angular Dependency Injection to inject it into a component.
- You gave the
HeroService
get data method an asynchronous signature. - You discovered
Observable
and the RxJS Observable library. - You used RxJS
of()
to return an observable of mock heroes (Observable
). - The component's
ngOnInit
lifecycle hook calls theHeroService
method, not the constructor. - You created a
MessageService
for loosely-coupled communication between classes. - The
Loose Korean New Asian Autumn Long Print Women's Top Vertical Stripe Size Sleeved Shirt Women Chiffon Classic HeroService
injected into a component is created with another injected service,MessageService
.
- An Angular event binding binds the button's click event to