Pada modul ini kita akan mulai implementasi untuk save ke Firebase dan fetch data dari Firebase.
Save Recipe
Buka file shared/data-storage.service.ts, lalu tambahkan method untuk save.
import { Injectable } from "@angular/core"; import { HttpClient } from "@angular/common/http"; 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); }); } }
Kemudian buka file header.component.html, tambakan click listener untuk save data.
<nav class="navbar navbar-expand-lg navbar-light bg-light"> <div class="container-fluid"> <a class="navbar-brand" href="#">Buku Resep</a> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarSupportedContent"> <ul class="navbar-nav me-auto mb-2 mb-lg-0"> <li class="nav-item"><a class="nav-link" routerLinkActive="active" routerLink="/recipes">Recipes</a></li> <li class="nav-item"><a class="nav-link" routerLinkActive="active" routerLink="/shopping-list" >Shopping List</a></li> </ul> <ul class="nav navbar-nav navbar-right"> <li class="dropdown" appDropDown> <a class="nav-link dropdown-toggle" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false" appDropdown> Manage </a> <ul class="dropdown-menu" aria-labelledby="navbarDropdown"> <!-- tambahkan click listener untuk save data --> <li><a class="dropdown-item" (click)="onSaveData()">Save Data</a></li> <li><a class="dropdown-item">Get Data</a></li> </ul> </li> </ul> </div> </div> </nav>
Buka file header.component.ts, implementasikan method untuk handling click listener diatas.
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(); } }
Jika test, dapat dilihat, data berhasil kita simpan di firebase.

Fetch Data Recipe
Buka file shared/data-storage.service.ts, kemudian tambahkan method untuk fetch recipe dari firebase.
Digunakan method pipe dan map untuk transform data response. Hal ini diperlukan karena ada kemungkinan recipe yang disave ke server tidak memiliki data ingredient.
Dengan melakukan maping, recipe yang tidak memiliki ingredients akan ditambahkan empty array.
fetchRecipes(){
this.http
.get<Recipe[]>('https://ng-buku-resep-c435d-default-rtdb.asia-southeast1.firebasedatabase.app/recipes.json')
//memastikan recipe yang di fetch memiliki item ingredients.
.pipe(map(recipes=>{
return recipes.map(recipe=>{
return {...recipe, ingredients: recipe.ingredients ? recipe.ingredients : []};
});
}))
.subscribe(recipes =>{
// console.log(recipes);
this.recipeSrv.setRecipes(recipes);
});
}
Kemudian buka file header.component.ts, tambahkan method untuk handling click listener ketika fetch data diclick.
onFetchData(){
this.dataStorageSrv.fetchRecipes();
}
Kemudian buka file header.component.html, tambahkan click listener pada menu fetch data. dengan menggunakan method diatas.
<li><a class="dropdown-item" (click)="onFetchData()">Get Data</a></li>
Kemudian buka file recipe.service.ts, tambahkan method untuk set recipe yang telah kita peroleh dari Firebase.
setRecipes(recipes : Recipe[]){
this.recipes = recipes;
this.recipeChange.next(this.recipes.slice());
}
Berikut isi lengkap file yang di modifikasi diatas:
File data-storage.service.ts
import { Injectable } from "@angular/core"; import { HttpClient } from "@angular/common/http"; import { map } 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(){ this.http .get<Recipe[]>('https://ng-buku-resep-c435d-default-rtdb.asia-southeast1.firebasedatabase.app/recipes.json') //memastikan recipe yang di fetch memiliki item ingredients. .pipe(map(recipes=>{ return recipes.map(recipe=>{ return {...recipe, ingredients: recipe.ingredients ? recipe.ingredients : []}; }); })) .subscribe(recipes =>{ // console.log(recipes); this.recipeSrv.setRecipes(recipes); }); } }
File header.component.html
<nav class="navbar navbar-expand-lg navbar-light bg-light"> <div class="container-fluid"> <a class="navbar-brand" href="#">Buku Resep</a> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarSupportedContent"> <ul class="navbar-nav me-auto mb-2 mb-lg-0"> <li class="nav-item"><a class="nav-link" routerLinkActive="active" routerLink="/recipes">Recipes</a></li> <li class="nav-item"><a class="nav-link" routerLinkActive="active" routerLink="/shopping-list" >Shopping List</a></li> </ul> <ul class="nav navbar-nav navbar-right"> <li class="dropdown" appDropDown> <a class="nav-link dropdown-toggle" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false" appDropdown> Manage </a> <ul class="dropdown-menu" aria-labelledby="navbarDropdown"> <!-- tambahkan click listener untuk save data --> <li><a class="dropdown-item" (click)="onSaveData()">Save Data</a></li> <li><a class="dropdown-item" (click)="onFetchData()">Get Data</a></li> </ul> </li> </ul> </div> </div> </nav>
File header.component.ts
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(); } }
File recipe.service.ts
import { Injectable } from "@angular/core"; import { Subject } from "rxjs"; import { Ingredient } from "../shared/ingredient.model"; import { ShoppingListService } from "../shopping-list/shopping-list.service"; import { Recipe } from "./recipe.model"; @Injectable() export class RecipeService{ recipeChange = new Subject<Recipe[]>(); // private recipes: Recipe[] = [ // new Recipe( // 'Oreo Dorayaki 1', // 'Doriyaki dengan bahan utama Oreo', // 'https://i.ytimg.com/vi/nJGmdqb892Y/maxresdefault.jpg', // [ // new Ingredient('Oreo', 1), // new Ingredient('Susu', 1), // ]), // new Recipe( // 'Oreo Dorayaki 2', // 'Doriyaki dengan bahan utama Oreo 2', // 'https://i.ytimg.com/vi/nJGmdqb892Y/maxresdefault.jpg', // [ // new Ingredient('Oreo', 1), // new Ingredient('Gula', 1), // ]) // ]; private recipes: Recipe[] = []; constructor (private shoppingListServ: ShoppingListService){} setRecipes(recipes : Recipe[]){ this.recipes = recipes; this.recipeChange.next(this.recipes.slice()); } getRecipes(){ return this.recipes.slice(); } getRecipe(idx : number){ return this.recipes[idx]; } addIngToShopList(ingredients : Ingredient[]){ this.shoppingListServ.addIngredients(ingredients); } addRecipe(recipe: Recipe){ this.recipes.push(recipe); this.recipeChange.next(this.recipes.slice()); } updRecipe(idx: number, updRecipe: Recipe){ this.recipes[idx] = updRecipe; this.recipeChange.next(this.recipes.slice()); } delRecipe(idx: number){ this.recipes.splice(idx, 1); this.recipeChange.next(this.recipes.slice()); } }
Karena data sudah disimpan di Firebase, kita bisa hapus hardcode recipe pada file recipe.service.ts.
Sampai disini kita sudah berhasil menggunakan http request untuk menyimpan dan menarik data.
Pada modul berikutnya kita akan melakukan data transforming.