While I have successfully implemented the GET, PUT, and DELETE methods using InMemoryDbService to simulate an API, I am facing issues with the CREATE method. It seems like the ID is not being generated in the route to display my add form. The error message displayed in the console is:
"url: 'api/pokemons/NaN'" and body : {error: "pokemons" with id = 'NaN' not found"
To keep things concise, I have omitted showing the mock-pokemon-list.ts file which simply consists of an array of data. Additionally, I have removed the methods that are functioning correctly from my files for clarity and ease of reading. I have already attempted to resolve this issue by referring to this topic on Stack Overflow: why genID() method in In-memory-web-api does not generate an ID? ... I hope my query is comprehensible and straightforward. Apologies for the length of the files. Thank you!
pokemon.module.ts (routes)
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule, Routes } from '@angular/router';
import { PokemonService } from './pokemon.service';
import { FormsModule } from '@angular/forms';
import { PokemonFormComponent } from './pokemon-form/pokemon-form.component';
import { AddPokemonComponent } from './add-pokemon/add-pokemon.component';
const pokemonRoutes: Routes = [
{ path: 'pokemon/add', component:AddPokemonComponent},
]
@NgModule({
declarations: [
PokemonFormComponent,
AddPokemonComponent
],
imports: [
CommonModule,
FormsModule,
RouterModule.forChild(pokemonRoutes)
],
providers: [PokemonService],
})
export class PokemonModule { }
in-memory-data-service.ts (we import data from mock-pokemon-list.ts which uses pokemon.ts class just after)
import { Injectable } from '@angular/core';
import { InMemoryDbService } from 'angular-in-memory-web-api';
import { POKEMONS } from './pokemon/mock-pokemon-list';
@Injectable({
providedIn: 'root'
})
export class InMemoryDataService implements InMemoryDbService {
createDb() {
const pokemons= POKEMONS;
return { pokemons };
}
}
pokemon.ts
export class Pokemon {
id:number;
name:string;
hp:number;
cp:number;
picture:string;
types:string[];
created:Date;
constructor(
name:string = 'Enter a name...',
hp: number = 100,
cp: number = 10,
picture: string = 'https://assets.pokemon.coom/assets/cms2/img/pokedex/detail/xxx.png',
types:string[] = ['Normal'],
created: Date = new Date()
) {
this.name=name;
this.hp=hp;
this.cp =cp;
this.picture = picture;
this.types = types;
this.created = created;
}
}
imports and add method in pokemon.service.ts
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Pokemon } from './pokemon';
import { catchError, Observable,of, tap } from 'rxjs';
@Injectable()
export class PokemonService {
constructor(private http: HttpClient){}
addPokemon(pokemon:Pokemon):Observable<Pokemon>{
const httpOptions = {
headers: new HttpHeaders({ 'Content-Type': 'application/json'})
};
return this.http.post<Pokemon>('api/pokemons', pokemon, httpOptions).pipe(
tap((response)=> this.log(response)),
catchError((error)=>this.handleError(error, null))
)
}
private log(response: any) {
console.table(response);
}
private handleError(error: Error, errorValue: any) {
console.error(error);
return of (errorValue);
}
}
add-pokemon.component.ts (a component which uses pokemon-form just below)
import { Component, OnInit } from '@angular/core';
import { Pokemon } from '../pokemon';
@Component({
selector: 'app-add-pokemon',
template: `
<app-pokemon-form [pokemon]="pokemon"></app-pokemon-form>
`,
})
export class AddPokemonComponent implements OnInit {
pokemon:Pokemon;
ngOnInit(): void {
this.pokemon = new Pokemon();
}
}
pokemon-form.component.ts
import { Component, Input, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { Pokemon } from '../pokemon';
import { PokemonService } from '../pokemon.service';
@Component({
selector: 'app-pokemon-form',
templateUrl: './pokemon-form.component.html',
styleUrls: ['./pokemon-form.component.css']
})
export class PokemonFormComponent implements OnInit {
@Input() pokemon:Pokemon;
types: string[];
isAddForm:boolean;
constructor(
private router:Router,
private pokemonService: PokemonService
) { }
ngOnInit() {
this.isAddForm = this.router.url.includes('add');
}
onSubmit() {
if(this.isAddForm) {
this.pokemonService.addPokemon(this.pokemon)
.subscribe((pokemon: Pokemon)=> this.router.navigate(['/pokemon', pokemon.id]));
}else {
this.pokemonService.updatePokemon(this.pokemon)
.subscribe(() => this.router.navigate(['/pokemon', this.pokemon.id]));
}
}
}
my button which initiates the action
<a class="btn-floating btn-large waves-effect waves-light red z-depth-3"
style="position: fixed; bottom: 25px; right: 25px;" routerLink="/pokemon/add"> + </a>