Menggunakan Http Request Pada Project Buku Resep – 3

Jika Anda lakukan test pada aplikasi Buku Resep, dengan mengakses path recipes secara langsung, akan terjadi error.

Hal ini terjadi karena Angular berusaha mengakses data yang belum tersedia di browser.

Ada beberapa pendekatan yang bisa dilakukan, misalnya dengan menjaga routing tertentu tidak bisa diakses.

Namun pada modul ini kami akan membahas pendekatan lain dengan menggunakan resolver.

Resolver sendiri adalah code yang dijalankan sebelum sebuah route diload. Berguna untuk memastikan data yang diperlukan oleh route tersebut sudah tersedia.

Buat file baru recipes/recipes-resolver.service.ts

import { Injectable } from "@angular/core";
import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from "@angular/router";

import { DataStorageService } from "../shared/data-storage.service";
import { Recipe } from "./recipe.model";
import { RecipeService } from "./recipe.service";

@Injectable({providedIn: "root"})
export class RecipesResolverService implements Resolve<Recipe[]>{
    constructor(private dataStorageSrv : DataStorageService, private recipeSrv : RecipeService){}

    resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
        const recipes = this.recipeSrv.getRecipes();
        if (recipes.length ===0){
            return this.dataStorageSrv.fetchRecipes();
        }else{
            return recipes;
        }
    }
}

Buka file data-storage.service.ts, lakukan modifikasi pada method fetchData(). Dimana proses subscribe akan dipindahkan ke component. Kemudian ditambahkan tap operator untuk mengakses data response agar tidak terjadi perubahan.

import { Injectable } from "@angular/core";
import { HttpClient } from "@angular/common/http";
import { map, tap } from "rxjs/operators";

import { Recipe } from "../recipes/recipe.model";
import { RecipeService } from "../recipes/recipe.service";

@Injectable({providedIn: 'root'})
export class DataStorageService{
    constructor(private http: HttpClient, private recipeSrv : RecipeService){}

    storeRecipes(){
        const recipes = this.recipeSrv.getRecipes();
        this.http
        .put('https://ng-buku-resep-c435d-default-rtdb.asia-southeast1.firebasedatabase.app/recipes.json',
            recipes)
        .subscribe(response =>{
            console.log(response);
        });
    }

    fetchRecipes(){
        return this.http
        .get<Recipe[]>('https://ng-buku-resep-c435d-default-rtdb.asia-southeast1.firebasedatabase.app/recipes.json')
        .pipe(
            map(recipes=>{
                return recipes.map(recipe=>{
                    return {...recipe, ingredients: recipe.ingredients ? recipe.ingredients : []};
                });
            }), 
            tap(recipes =>{
                this.recipeSrv.setRecipes(recipes);
            })
        );
    }
}

Karena proses subscribe akan dilakukan pada component, buka file header.component.ts, lakukan subscribe.

import { Component } from "@angular/core";
import { DataStorageService } from "../shared/data-storage.service";

@Component({
    selector: 'app-header',
    templateUrl: './header.component.html'
})

export class HeaderComponent{
    constructor(private dataStorageSrv : DataStorageService){}

    onSaveData(){
        this.dataStorageSrv.storeRecipes();
    }

    onFetchData(){
        this.dataStorageSrv.fetchRecipes().subscribe();
    }
}

Kemudian kita buka app-routing.module.ts, untuk mengaplikasikan resolver.

import { NgModule } from "@angular/core";
import { RouterModule, Routes } from "@angular/router";
import { RecipeDetailComponent } from "./recipes/recipe-detail/recipe-detail.component";
import { RecipeEditComponent } from "./recipes/recipe-edit/recipe-edit.component";
import { RecipeHomeComponent } from "./recipes/recipe-home/recipe-home.component";
import { RecipesComponent } from "./recipes/recipes.component";
import { ShoppingListComponent } from "./shopping-list/shopping-list.component";
//import library RecipesResolverService
import { RecipesResolverService } from "./recipes/recipes-resolver.service";

const appRoutes: Routes = [
    {path: '', redirectTo:'/recipes', pathMatch: 'full'},
    {path: 'recipes', component: RecipesComponent, children:[  
        {path: '', component: RecipeHomeComponent},
        {path: 'new', component: RecipeEditComponent},
        //tambahkan resolver
        {path: ':id', component: RecipeDetailComponent, resolve: [RecipesResolverService]},
        {path: ':id/edit', component: RecipeEditComponent, resolve: [RecipesResolverService]}
    ]},
    {path: 'shopping-list', component: ShoppingListComponent},
];

@NgModule({
    imports: [RouterModule.forRoot(appRoutes)],
    exports: [RouterModule]
})
export class AppRoutingModule{
}

Jika dijalankan, error yang terjadi diatas akan hilang, karena saat route recipes diakses, resolver akan melakukan data fetch.

Sharing is caring:

Leave a Comment