dane z backendu

omówię:

- wykorzystanie httpClient
- czym jest observable
- czym jest subscription oraz dwa sposoby subskrypcji

W folderze car tam gdzie utworzyłeś car.interface.ts dodaj serwis o nazwie car.service.ts. Możesz go dodać ręcznie albo poprzez konsolę i Angular CLI wpisując komendą ng g s car. (ng generate service car)

import { Injectable } from '@angular/core';

@Injectable({
providedIn: 'root'
})
export class CarService {

constructor() { }
}

Przenieś listę samochodów z komponentu app.component.ts do serwisu

import {Injectable} from '@angular/core';
import {Car} from './car.interface';
import {Observable, of} from 'rxjs';

@Injectable(
{
providedIn: 'root'
}
)
export class CarService {
public fetchAvailableCars(): Observable<Car[]> {
return of([
{
brand: 'AUDI',
model: 'RS7',
vin: '1HGEJ814XVL168593',
engineType: 'petrol',
type: 'sedan',
price: 250450,
photoSource: 'https://www.szkolaangulara.pl/wp-content/uploads/2020/05/3-small.jpeg'
},
{
brand: 'Mercedes',
model: 'GT',
vin: '1C3BC1FB1BN610126',
engineType: 'petrol',
type: 'coupe',
price: 598900,
photoSource: 'https://www.szkolaangulara.pl/wp-content/uploads/2020/05/4-small.jpeg'
},
{
brand: 'AUDI',
model: 'A3',
vin: '3C7WDTCL6CG300411',
engineType: 'petrol',
type: 'sedan',
price: 170000,
photoSource: 'https://www.szkolaangulara.pl/wp-content/uploads/2020/05/5-small.jpeg'
},
{
brand: 'Mercedes',
model: 'KLASA G',
vin: '1G1YY32G425115593',
engineType: 'petrol',
type: 'suv',
price: 654000,
photoSource: 'https://www.szkolaangulara.pl/wp-content/uploads/2020/05/6-small.jpeg'
},
{
brand: 'BMW',
model: 'SERIA 3',
vin: '2HNYD18281H533966',
engineType: 'petrol',
type: 'coupe',
price: 73400,
photoSource: 'https://www.szkolaangulara.pl/wp-content/uploads/2020/05/7-small.jpeg'
},
{
brand: 'Nissan',
model: '370z',
vin: '4M2DU86W22ZJ33397',
engineType: 'petrol',
type: 'coupe',
price: 125000,
photoSource: 'https://www.szkolaangulara.pl/wp-content/uploads/2020/05/8-small.jpeg'
}
]);
}
}

Nowością w powyższym kodzie jest opakowanie odpowiedzi w typ Observable. Zastosujemy taką konstrukcję ponieważ odpowiedzi z backendu przy użyciu httpClient są właśnie opakowywane w typ Observable. W dużym uproszczeniu Observable to strumień który daje Ci wiele możliwości jak m.in. mapowanie danych, filtrowanie, łączenie strumieni itd. Tym zajmiemy się w kolejnej lekcji podczas mapowania odpowiedzi z interfejsu na model. 

Operatory mapowania, mergowania, filtorwania itd. są operatorami RxJs. Jest to związanie z programowaniem reaktywnym. Więcej o operatorach znajdziesz na stronie learn RxJs.

Przejdź do app.componet.ts

import {Component, OnInit} from '@angular/core';
import {CarService} from './car/car.service';
import {Car} from './car/car.interface';

@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
selectedCar: Car;
cars: Car[] = [];

public ngOnInit(): void { // 2
this.carService.fetchAvailableCars()
.subscribe(cars => { // 3
this.cars = cars;
});
}

constructor(private carService: CarService) { // 1
}


public carSelected(vin: string): void {
this.selectedCar = this.cars
.find(car => car.vin === vin);
}


public resetCarSection() {
this.selectedCar = null;
}
}

Zmiany jakie wprowadziliśmy to:

1) wstrzyknięcie serwisu car.service w konstruktorze

2) implementacja interfejsu OnInit oraz nadpisanie metody ngOnInit -> uczyliśmy się o tym tutaj

3) zastosowanie mechanizmu subskrybowania. Subskrybcja odbywa się na obiekcie typu Observable po subskrypcji dostaniesz dostęp do wartości którą Observable przechowuje. W tym przypadku będzie to lista samochodów. 

Ostatnim krokiem który musimy zrobić to przenieść dane do backendu i pobrać je w serwisie car.service.ts przy użyciu httpClient.

Pobierz cześć serwerową z GitHub. Jest to bardzo prosty backend, który wysyła wszystkie dostępne samochody pod adresem localhost:8080/cars.

Aby zacząć korzystać z httpClient’a musisz dodać moduł HttpClientModule do app.module.ts.

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

import {AppComponent} from './app.component';
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
import {MatButtonModule, MatCardModule} from '@angular/material';
import {CardComponent} from './card/card.component';
import {HttpClientModule} from '@angular/common/http';

@NgModule({
declarations: [
AppComponent,
CardComponent
],
imports: [
BrowserModule,
BrowserAnimationsModule,
MatCardModule,
MatButtonModule,
HttpClientModule, // <-----
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule {
}

Musisz jeszcze dostosować car.service.ts do pobrania danych z backendu.

import {Injectable} from '@angular/core';
import {Observable} from 'rxjs';
import {HttpClient} from '@angular/common/http';
import {Car} from './car.interface';

@Injectable(
{
providedIn: 'root'
}
)
export class CarService {
constructor(private httpClient: HttpClient) { // 1
}

public fetchAvailableCars(): Observable<Car[]> { // 2
return this.httpClient.get<Car[]>('http://localhost:8080/cars');
}
}

1) wstrzyknięcie httpClient

2) wykorzystanie httpClient w tym przypadku użycie metody HTTP GET, która łączy się z backendem poprzez podanie namiaru na endpoint z którego chcemy pobrać dane

Interfejs car.interface.ts posiada takie same pola jak dane z backendu i dzięki temu zachodzi automatyczne mapowanie na interfejs Car. Tak jak wspominałem, gdy używamy httpClient’a to odpowiedzi są opakowywane w typ Observable.