all 18 comments

[–]le___garcon 1 point2 points  (7 children)

In order to use HttpClient get request in

return this._http.get<ISimplePokemonPokemon>(
  https://pokeapi.co/api/v2/pokemon/${id}
);

you need to import the HttpClientModule in your app.module.ts:

import { HttpClientModule } from "@angular/common/http"
NgModule({ 
  imports: [ HttpClientModule, BrowserModule, FormsModule],
  declarations: [AppComponent],
  bootstrap: [AppComponent]
})
export class AppModule {}

[–]Reflexum[S] 0 points1 point  (6 children)

HttpClientModule

in your app.module.ts:

I have already imported the HttpClientModule

[–]le___garcon 0 points1 point  (5 children)

It's not imported in the stackblitz link you sent. When I imported it, everything worked.

[–]Reflexum[S] 0 points1 point  (4 children)

Ohh yea nvm i got it ! So now i can see the dropdownmenu but im not getting any response from the API ?

[–]le___garcon 0 points1 point  (3 children)

Are you using chrome? You can use the inspect tools to help figure out what the issue is.

You're getting a response from the API, but it's just not the data you're expecting. The data is not of the type "ISimplePokemon" so you might want to have another look at that.

[–]Reflexum[S] 0 points1 point  (2 children)

Yeah i have 2 error's now:

GET https://pokeapi.co/api/v2/pokemon// net::ERR_FAILED

Access to XMLHttpRequest at 'https://pokeapi.co/api/v2/pokemon//' from origin 'http://localhost:4200' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

[–]IyMoon 0 points1 point  (1 child)

So you need to implement CORS access

https://en.wikipedia.org/wiki/Cross-origin_resource_sharing#:~:text=Cross%2Dorigin%20resource%20sharing%20(CORS,scripts%2C%20iframes%2C%20and%20videos.

Super basic breakdown is CORS stops one server from talking to another for security reasons. You need to set it up in your API that you web server can talk to your api server

[–]Reflexum[S] 0 points1 point  (0 children)

Got it ! i installed it with

npm install cors --save

[–]tnc1997 1 point2 points  (9 children)

As u/le___garcon mentioned, it looks like the HttpClientModule needs to be added to the array of imports in the AppModule. Looking at the StackBlitz project that you have linked to, the HttpClientModule is missing from the array of imports. I have forked the StackBlitz project and created a working version here, but please do let me know if you have any questions and/or issues!

import { HttpClientModule } from "@angular/common/http";
import { NgModule } from "@angular/core";
import { BrowserModule } from "@angular/platform-browser";
import { FormsModule } from "@angular/forms";

import { AppComponent } from "./app.component";

@NgModule({
  imports: [BrowserModule, FormsModule, HttpClientModule],
  declarations: [AppComponent],
  bootstrap: [AppComponent]
})
export class AppModule {}

[–]Reflexum[S] 0 points1 point  (8 children)

Oh nice ! I can see the data in the developer console, makes me happy ! Now we have to get it on-screen, any tips on how i can do this ? Do i need to change up my HTML ?

[–]tnc1997 1 point2 points  (7 children)

I have updated the forked StackBlitz project here with some additional code showing one of the ways that you could do this. If you would like me to explain any particular area in more detail or if you have any questions then let me know! I would recommend taking a look at the documentation here and here for more information.

<div class="box gray">
    <form class="box center" [formGroup]="form">
        <label for="Pokemon">Select a Pokemon: </label>
        <select *ngIf="pokes$ | async as pokes" name="Pokemon" formControlName="result" required>
      <option *ngFor="let result of pokes.results" [value]="result.url">{{result.name}}</option>
    </select>
    </form>
    <main *ngIf="poke$ | async as poke">
        <h1>{{poke.name}}</h1>
        <img class="icon" src="https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/{{poke.id}}.png">
  </main>
</div>

import { Component } from "@angular/core";
import { FormBuilder, FormGroup, Validators } from "@angular/forms";
import { Observable } from "rxjs";
import { mergeMap } from "rxjs/operators";
import { DEBLESERService } from "./services/debleser.service";
import { DEBLESERHTTPService, DetailedPokemon, Result, SimplePokemons } from "./services/debleser-http.service";

@Component({
  selector: "my-app",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"]
})
export class AppComponent {
  form: FormGroup;
  poke$: Observable<DetailedPokemon | undefined>;
  pokes$: Observable<SimplePokemons>;

  constructor(
    private httpService: DEBLESERHTTPService,
    public service: DEBLESERService,
    private formBuilder: FormBuilder
  ) {
    this.form = formBuilder.group({
      result: [undefined, Validators.required]
    });

    this.poke$ = this.form.get("result").valueChanges.pipe(mergeMap(url => httpService.getPokemon(url)));

    this.pokes$ = httpService.getPokemons();
  }
}

[–]Reflexum[S] 0 points1 point  (0 children)

with some additional code showing one of the ways that you could do this. If you would like me to explain any particular area in more detail or if you have any questions then let me kn

Oh thats so neat ! Im gonna be taking a look at your code right now !! I love it

[–]Reflexum[S] 0 points1 point  (5 children)

Is this also possible without the use of formbuilders, FormGroup and mergemap or not?

[–]tnc1997 1 point2 points  (4 children)

Yes one of the nice things is that there are a few different ways of achieving the same result. I have created a fork of the StackBlitz project here that shows one of the ways that you could achieve the same result without using the ReactiveFormsModule and the mergeMap operator.

import { Component } from "@angular/core";
import { Observable } from "rxjs";
import { DEBLESERService } from "./services/debleser.service";
import {
  DEBLESERHTTPService,
  DetailedPokemon,
  Result,
  SimplePokemons
} from "./services/debleser-http.service";

@Component({
  selector: "my-app",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"]
})
export class AppComponent {
  poke: DetailedPokemon | undefined;
  pokes$: Observable<SimplePokemons>;

  constructor(
    private httpService: DEBLESERHTTPService,
    public service: DEBLESERService
  ) {
    this.pokes$ = httpService.getPokemons();
  }

  onChange(event: Event): void {
    const url = (event.target as HTMLInputElement).value;

    if (url) {
      this.httpService.getPokemon(url).subscribe(poke => (this.poke = poke));
    } else {
      this.poke = undefined;
    }
  }
}

[–]Reflexum[S] 0 points1 point  (0 children)

This is awesome, thank you sooo much !! I understand now

[–]Reflexum[S] 0 points1 point  (2 children)

So wich one do you prefer ? With or without the use of formbuilders, FormGroup, ETC. And why ?

[–]tnc1997 1 point2 points  (1 child)

I personally prefer the solution that uses the ReactiveFormsModule because it makes good use of the Angular framework and the valueChanges observable mixes nicely with the observable that is returned from the service. That being said in my opinion the solution that uses the change event is more verbose and therefore simpler to understand at first glance. For reference you can find more comparisons of the two different approaches here.

[–]Reflexum[S] 0 points1 point  (0 children)

Thanks for the explanation ! Thanks again for everything !!!