Bu eğitim, HTTP ve bir API'yi uygulamanıza nasıl entegre edeceğinizi gösterir.
Bu noktaya kadar uygulamanız, bir Angular servisindeki statik bir diziden veri okumuştur. Bir sonraki adım, uygulamanızın HTTP üzerinden iletişim kuracağı bir JSON sunucusu kullanmaktır. HTTP isteği, bir sunucudan gelen verilerle çalışma deneyimini simüle edecektir.
IMPORTANT: Eğitimin bu adımı için yerel ortamınızı kullanmanızı öneriyoruz.
Neler öğreneceksiniz
Uygulamanız bir JSON sunucusundan veri kullanacak
-
JSON sunucusunu yapılandırın
JSON Server, sahte REST API'ler oluşturmak için kullanılan açık kaynaklı bir araçtır. Bunu, şu anda konut servisinde depolanan konut konumu verilerini sunmak için kullanacaksınız.
Aşağıdaki komutu kullanarak npm'den
json-serveryükleyin.npm install -g json-serverProjenizin kök dizininde,
db.jsonadında bir dosya oluşturun. Bu,json-serveriçin verilerin depolanacağı yerdir.db.jsondosyasını açın ve aşağıdaki kodu dosyaya kopyalayın{ "locations": [ { "id": 0, "name": "Acme Fresh Start Housing", "city": "Chicago", "state": "IL", "photo": "https://angular.dev/assets/images/tutorials/common/bernard-hermant-CLKGGwIBTaY-unsplash.jpg", "availableUnits": 4, "wifi": true, "laundry": true }, { "id": 1, "name": "A113 Transitional Housing", "city": "Santa Monica", "state": "CA", "photo": "https://angular.dev/assets/images/tutorials/common/brandon-griggs-wR11KBaB86U-unsplash.jpg", "availableUnits": 0, "wifi": false, "laundry": true }, { "id": 2, "name": "Warm Beds Housing Support", "city": "Juneau", "state": "AK", "photo": "https://angular.dev/assets/images/tutorials/common/i-do-nothing-but-love-lAyXdl1-Wmc-unsplash.jpg", "availableUnits": 1, "wifi": false, "laundry": false }, { "id": 3, "name": "Homesteady Housing", "city": "Chicago", "state": "IL", "photo": "https://angular.dev/assets/images/tutorials/common/ian-macdonald-W8z6aiwfi1E-unsplash.jpg", "availableUnits": 1, "wifi": true, "laundry": false }, { "id": 4, "name": "Happy Homes Group", "city": "Gary", "state": "IN", "photo": "https://angular.dev/assets/images/tutorials/common/krzysztof-hepner-978RAXoXnH4-unsplash.jpg", "availableUnits": 1, "wifi": true, "laundry": false }, { "id": 5, "name": "Hopeful Apartment Group", "city": "Oakland", "state": "CA", "photo": "https://angular.dev/assets/images/tutorials/common/r-architecture-JvQ0Q5IkeMM-unsplash.jpg", "availableUnits": 2, "wifi": true, "laundry": true }, { "id": 6, "name": "Seriously Safe Towns", "city": "Oakland", "state": "CA", "photo": "https://angular.dev/assets/images/tutorials/common/phil-hearing-IYfp2Ixe9nM-unsplash.jpg", "availableUnits": 5, "wifi": true, "laundry": true }, { "id": 7, "name": "Hopeful Housing Solutions", "city": "Oakland", "state": "CA", "photo": "https://angular.dev/assets/images/tutorials/common/r-architecture-GGupkreKwxA-unsplash.jpg", "availableUnits": 2, "wifi": true, "laundry": true }, { "id": 8, "name": "Seriously Safe Towns", "city": "Oakland", "state": "CA", "photo": "https://angular.dev/assets/images/tutorials/common/saru-robert-9rP3mxf8qWI-unsplash.jpg", "availableUnits": 10, "wifi": false, "laundry": false }, { "id": 9, "name": "Capital Safe Towns", "city": "Portland", "state": "OR", "photo": "https://angular.dev/assets/images/tutorials/common/webaliser-_TPTXZd9mOo-unsplash.jpg", "availableUnits": 6, "wifi": true, "laundry": true } ] }Bu dosyayı kaydedin.
Yapılandırmanızı test etme zamanı. Komut satırından, projenizin kök dizininde aşağıdaki komutları çalıştırın.
json-server --watch db.jsonWeb tarayıcınızda,
http://localhost:3000/locationsadresine gidin ve yanıtındb.jsondosyasında depolanan verileri içerdiğini doğrulayın.
Yapılandırmanızda herhangi bir sorun yaşarsanız, resmi belgelerden daha fazla ayrıntı bulabilirsiniz.
-
Servisi yerel dizi yerine web sunucusu kullanacak şekilde güncelleyin
Veri kaynağı yapılandırıldı, bir sonraki adım web uygulamanızı buna bağlanacak ve verileri kullanacak şekilde güncellemektir.
src/app/housing.service.tsdosyasında aşağıdaki değişiklikleri yapın:housingLocationListözelliğini ve verileri içeren diziyi, ayrıcabaseUrlözelliğini kaldırmak için kodu güncelleyin.urladında bir string özelliği ekleyin ve değerini'http://localhost:3000/locations'olarak ayarlayınAdd url property to housing.service.ts
import {Injectable} from '@angular/core'; import {HousingLocationInfo} from './housinglocation'; @Injectable({ providedIn: 'root', }) export class HousingService { url = 'http://localhost:3000/locations'; async getAllHousingLocations(): Promise<HousingLocationInfo[]> { const data = await fetch(this.url); return (await data.json()) ?? []; } async getHousingLocationById(id: number): Promise<HousingLocationInfo | undefined> { const data = await fetch(`${this.url}/${id}`); const locationJson = await data.json(); return locationJson ?? {}; } submitApplication(firstName: string, lastName: string, email: string) { // tslint:disable-next-line console.log(firstName, lastName, email); } }Bu kod, dosyanın geri kalanında hatalara neden olacaktır çünkü
housingLocationListözelliğine bağımlıdır. Servis metotlarını şimdi güncelleyeceğiz.getAllHousingLocationsfonksiyonunu, yapılandırdığınız web sunucusuna bir çağrı yapacak şekilde güncelleyin.Update the getAllHousingLocations method in housing.service.ts
import {Injectable} from '@angular/core'; import {HousingLocationInfo} from './housinglocation'; @Injectable({ providedIn: 'root', }) export class HousingService { url = 'http://localhost:3000/locations'; async getAllHousingLocations(): Promise<HousingLocationInfo[]> { const data = await fetch(this.url); return (await data.json()) ?? []; } async getHousingLocationById(id: number): Promise<HousingLocationInfo | undefined> { const data = await fetch(`${this.url}/${id}`); const locationJson = await data.json(); return locationJson ?? {}; } submitApplication(firstName: string, lastName: string, email: string) { // tslint:disable-next-line console.log(firstName, lastName, email); } }Kod artık HTTP üzerinden bir GET isteği yapmak için asenkron kod kullanmaktadır.
HELPFUL: Bu örnek için kod
fetchkullanmaktadır. Daha gelişmiş kullanım durumları için Angular tarafından sağlananHttpClientkullanmayı düşünün.getHousingLocationsByIdfonksiyonunu, yapılandırdığınız web sunucusuna bir çağrı yapacak şekilde güncelleyin.HELPFUL:
fetchmetodunun, eşleşenidözellik değerine sahip konum verilerini sorgulamak için güncellendiğine dikkat edin. Daha fazla bilgi için URL Arama Parametresi bölümüne bakın.Update the getHousingLocationById method in housing.service.ts
import {Injectable} from '@angular/core'; import {HousingLocationInfo} from './housinglocation'; @Injectable({ providedIn: 'root', }) export class HousingService { url = 'http://localhost:3000/locations'; async getAllHousingLocations(): Promise<HousingLocationInfo[]> { const data = await fetch(this.url); return (await data.json()) ?? []; } async getHousingLocationById(id: number): Promise<HousingLocationInfo | undefined> { const data = await fetch(`${this.url}/${id}`); const locationJson = await data.json(); return locationJson ?? {}; } submitApplication(firstName: string, lastName: string, email: string) { // tslint:disable-next-line console.log(firstName, lastName, email); } }Tüm güncellemeler tamamlandığında, güncellenmiş servisiniz aşağıdaki kodla eşleşmelidir.
Final version of housing.service.ts
import {Injectable} from '@angular/core'; import {HousingLocationInfo} from './housinglocation'; @Injectable({ providedIn: 'root', }) export class HousingService { url = 'http://localhost:3000/locations'; async getAllHousingLocations(): Promise<HousingLocationInfo[]> { const data = await fetch(this.url); return (await data.json()) ?? []; } async getHousingLocationById(id: number): Promise<HousingLocationInfo | undefined> { const data = await fetch(`${this.url}/${id}`); const locationJson = await data.json(); return locationJson ?? {}; } submitApplication(firstName: string, lastName: string, email: string) { // tslint:disable-next-line console.log(firstName, lastName, email); } }
-
Bileşenleri konut servisine asenkron çağrılar kullanacak şekilde güncelleyin
Sunucu artık HTTP isteğinden veri okuyor ancak servise bağımlı olan bileşenler, servisin senkron sürümünü kullanmak üzere programlandıkları için artık hata vermektedir.
src/app/home/home.tsdosyasında,constructor'ı yeni asenkrongetAllHousingLocationsmetodu sürümünü kullanacak şekilde güncelleyin. Durumumuz için sinyaller kullanmadığımızdan, Angular'a bir değişiklik olduğunu ve senkronizasyon gerektirdiğini bildirmeniz gerekir. Bunu yapmak içinthis.changeDetectorRef.markForCheck()çağrısını yapın.Update constructor in home.ts
import {ChangeDetectorRef, Component, inject} from '@angular/core'; import {HousingLocation} from '../housing-location/housing-location'; import {HousingLocationInfo} from '../housinglocation'; import {HousingService} from '../housing.service'; @Component({ selector: 'app-home', imports: [HousingLocation], template: ` <section> <form> <input type="text" placeholder="Filter by city" #filter /> <button class="primary" type="button" (click)="filterResults(filter.value)">Search</button> </form> </section> <section class="results"> @for (housingLocation of filteredLocationList; track $index) { <app-housing-location [housingLocation]="housingLocation" /> } </section> `, styleUrls: ['./home.css'], }) export class Home { private readonly changeDetectorRef = inject(ChangeDetectorRef); housingLocationList: HousingLocationInfo[] = []; housingService: HousingService = inject(HousingService); filteredLocationList: HousingLocationInfo[] = []; constructor() { this.housingService .getAllHousingLocations() .then((housingLocationList: HousingLocationInfo[]) => { this.housingLocationList = housingLocationList; this.filteredLocationList = housingLocationList; this.changeDetectorRef.markForCheck(); }); } filterResults(text: string) { if (!text) { this.filteredLocationList = this.housingLocationList; return; } this.filteredLocationList = this.housingLocationList.filter((housingLocation) => housingLocation?.city.toLowerCase().includes(text.toLowerCase()), ); } }src/app/details/details.tsdosyasında,constructor'ı yeni asenkrongetHousingLocationByIdmetodu sürümünü kullanacak şekilde güncelleyin. Daha önce olduğu gibi, değişiklikleri Angular'a bildirmek içinthis.changeDetectorRef.markForCheck()çağrısını da yapmalısınız.Update constructor in details.ts
import {ChangeDetectorRef, Component, inject} from '@angular/core'; import {ActivatedRoute} from '@angular/router'; import {HousingService} from '../housing.service'; import {HousingLocationInfo} from '../housinglocation'; import {FormControl, FormGroup, ReactiveFormsModule} from '@angular/forms'; @Component({ selector: 'app-details', imports: [ReactiveFormsModule], template: ` <article> <img class="listing-photo" [src]="housingLocation?.photo" alt="Exterior photo of {{ housingLocation?.name }}" crossorigin /> <section class="listing-description"> <h2 class="listing-heading">{{ housingLocation?.name }}</h2> <p class="listing-location">{{ housingLocation?.city }}, {{ housingLocation?.state }}</p> </section> <section class="listing-features"> <h2 class="section-heading">About this housing location</h2> <ul> <li>Units available: {{ housingLocation?.availableUnits }}</li> <li>Does this location have wifi: {{ housingLocation?.wifi }}</li> <li>Does this location have laundry: {{ housingLocation?.laundry }}</li> </ul> </section> <section class="listing-apply"> <h2 class="section-heading">Apply now to live here</h2> <form [formGroup]="applyForm" (submit)="submitApplication()"> <label for="first-name">First Name</label> <input id="first-name" type="text" formControlName="firstName" /> <label for="last-name">Last Name</label> <input id="last-name" type="text" formControlName="lastName" /> <label for="email">Email</label> <input id="email" type="email" formControlName="email" /> <button type="submit" class="primary">Apply now</button> </form> </section> </article> `, styleUrls: ['./details.css'], }) export class Details { private readonly changeDetectorRef = inject(ChangeDetectorRef); route: ActivatedRoute = inject(ActivatedRoute); housingService = inject(HousingService); housingLocation: HousingLocationInfo | undefined; applyForm = new FormGroup({ firstName: new FormControl(''), lastName: new FormControl(''), email: new FormControl(''), }); constructor() { const housingLocationId = parseInt(this.route.snapshot.params['id'], 10); this.housingService.getHousingLocationById(housingLocationId).then((housingLocation) => { this.housingLocation = housingLocation; this.changeDetectorRef.markForCheck(); }); } submitApplication() { this.housingService.submitApplication( this.applyForm.value.firstName ?? '', this.applyForm.value.lastName ?? '', this.applyForm.value.email ?? '', ); } }Kodunuzu kaydedin.
Uygulamayı tarayıcıda açın ve herhangi bir hata olmadan çalıştığını doğrulayın.
NOTE: Bu ders tarayıcı fetch API'sine dayanmaktadır. Interceptor desteği için lütfen HTTP client belgelerine bakın.
SUMMARY: Bu derste, uygulamanızı yerel bir web sunucusu (json-server) kullanacak şekilde güncellediniz ve veri almak için asenkron servis metotlarını kullandınız.
Tebrikler! Bu eğitimi başarıyla tamamladınız ve daha karmaşık Angular Uygulamaları oluşturma yolculuğunuza devam etmeye hazırsınız.
Daha fazla bilgi edinmek isterseniz, Angular'ın diğer geliştirici eğitimlerini ve kılavuzlarını tamamlamayı düşünebilirsiniz.