@Component
is a decorator function that specifies the Angular metadata for the component.Styles and stylesheets identified in
@Component
metadata are scoped to that specific component. The heroes.component.css
styles apply only to the HeroesComponent
and don't affect the outer HTML or the HTML in any other component.@Injectable() services
Notice that the new service imports the Angular
Injectable
symbol and annotates the class with the @Injectable()
decorator.
The
@Injectable()
decorator tells Angular that this service might itself have injected dependencies. It doesn't have dependencies now but it will soon. Whether it does or it doesn't, it's good practice to keep the decorator.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.Add routes
Routes tell the router which view to display when a user clicks a link or pastes a URL into the browser address bar.
A typical Angular
Route
has two properties:path
: a string that matches the URL in the browser address bar.component
: the component that the router should create when navigating to this route.
RouterModule.forRoot()
You first must initialize the router and start it listening for browser location changes.
Add
RouterModule
to the @NgModule.imports
array and configure it with the routes
in one step by calling RouterModule.forRoot()
within the imports
array, like this:imports: [ RouterModule.forRoot(routes) ],
The method is called
forRoot()
because you configure the router at the application's root level. The forRoot()
method supplies the service providers and directives needed for routing, and performs the initial navigation based on the current browser URL.Add RouterOutlet
<h1>{{title}}</h1>
<router-outlet></router-outlet>
<app-messages></app-messages>
You removed
<app-heroes>
because you will only display the HeroesComponent
when the user navigates to it.
The
<router-outlet>
tells the router where to display routed views.
The
RouterOutlet
is one of the router directives that became available to the AppComponent
because AppModule
imports AppRoutingModule
which exported RouterModule
.
Add a navigation link (routerLink
)
Users shouldn't have to paste a route URL into the address bar. They should be able to click a link to navigate.
Add a
<nav>
element and, within that, an anchor element that, when clicked, triggers navigation to the HeroesComponent
. The revised AppComponent
template looks like this:<h1>{{title}}</h1>
<nav>
<a routerLink="/heroes">Heroes</a>
</nav>
<router-outlet></router-outlet>
<app-messages></app-messages>
A
routerLink
attribute is set to "/heroes"
, the string that the router matches to the route to HeroesComponent
. The routerLink
is the selector for the RouterLink
directive that turns user clicks into router navigations. It's another of the public directives in the RouterModule
.
The browser refreshes and displays the app title and heroes link, but not the heroes list.
Click the link. The address bar updates to
/heroes
and the list of heroes appears.
Make this and future navigation links look better by adding private CSS styles to
app.component.css
as listed in the final code review below.Enable HTTP services
HttpClient
is Angular's mechanism for communicating with a remote server over HTTP.
To make
HttpClient
available everywhere in the app,- open the root
AppModule
, - import the
HttpClientModule
symbol from@angular/common/http
, - add it to the
@NgModule.imports
array.
Http methods return one value
All
HttpClient
methods return an RxJS Observable
of something.
HTTP is a request/response protocol. You make a request, it returns a single response.
In general, an
Observable
can return multiple values over time. An Observable
from HttpClient
always emits a single value and then completes, never to emit again.
This particular
HttpClient.get
call returns an Observable<Hero[]>
, literally "an observable of hero arrays". In practice, it will only return a single hero array.HttpClient.get returns response data
HttpClient.get
returns the body of the response as an untyped JSON object by default. Applying the optional type specifier, <Hero[]>
, gives you a typed result object.
The shape of the JSON data is determined by the server's data API. The Tour of Heroes data API returns the hero data as an array.
If you neglect to
subscribe()
, the service will not send the delete request to the server! As a rule, an Observable
does nothing until something subscribes!AsyncPipe
As expected, the
*ngFor
repeats hero objects.<li *ngFor="let hero of heroes$ | async" >
The
$
is a convention that indicates heroes$
is an Observable
, not an array.
The
*ngFor
can't do anything with an Observable
. But there's also a pipe character (|
) followed by async
, which identifies Angular's AsyncPipe
.
The
AsyncPipe
subscribes to an Observable
automatically so you won't have to do so in the component class.
Không có nhận xét nào:
Đăng nhận xét