0

I'm working on my first Angular2 project (building a Pokemon web app), and I keep getting the following error messages when trying to load the page:

failed to compile.

/home/mattlayton1986/workspace/pokedex/src/app/pokedex.service.ts (26,20): Cannot find name 'p'.
/home/mattlayton1986/workspace/pokedex/src/app/pokedex.service.ts (26,23): Cannot find name 'i'.

The error is occurring inside my ./pokedex-service.ts' file, which loads the data from the API and gets injected into the component. Here is all the code in myPokedexService` file:

import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import 'rxjs/add/operator/toPromise';

@Injectable()
export class PokedexService {
  private baseUrl: string = 'https://pokeapi.co/api/v2/pokemon/';
  private baseSpriteUrl: string = 'https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/';

  constructor(private http: Http) { }

  getPokemon(offset: number, limit: number) {
    return this.http.get(
      `${this.baseUrl}?offset=${offset}&limit=${limit}`
    ).toPromise().then(
      response => response.json().results
    ).then(items => items.map(
      (poke, idx) => {
        const id: number = idx + offset + 1;
        return {
          id,
          name: poke.name,
          sprite: `${this.baseSpriteUrl}${id}.png`
        };
      }
    ).map(getTypes(p, i))); // <-- error occurs here
  }
}

function getTypes(pokemon, id) {
  return this.http.get(
    `${this.baseUrl}${id}`
  ).toPromise().then(
    response => response.json().results
  ).then(item => item.map(
    poke => {
      return {
        poke,
        type1: poke.types.type[0].name,
        type2: poke.types.type[1].name
      }
    }
  ));
}

For reference, in case it helps, here is my main component and its template, which makes use of the service to load Pokemon data:

app.component.html

<h1>Angular 2 Pokedex</h1>

<span>This is a sample app using Angular 2 RC5. Check out the <a href="https://github.com/argelius/angular2-pokedex">source code here</a></span>

<hr />

<div class="pokedex">
  <div class="pokedex-pokemon" *ngFor="let p of pokemon" [pokemonTypes]="p">
    <div class="pokedex-pokemon-id">
      {{p.id}}
    </div>
    <img [ngClass]="{'hidden': !p.imageLoaded}" class="pokedex-pokemon-sprite" (load)="p.imageLoaded = true" [attr.src]="p.sprite" />
    <div class="pokedex-pokemon-name">
      {{ p.name | capitalize }}
    </div>
    <div class="pokedex-pokemon-type1">
      {{ p.types.type1 }}
    </div>
    <div calss="pokedex-pokemon-type2">
      {{ p.types.type2 }}
    </div>
  </div>
</div>

<button class="load-button" (click)="loadMore()" [disabled]="isLoading">
  <span *ngIf="!error">
    <span *ngIf="isLoading">Loading...</span>
    <span *ngIf="!isLoading">Load more</span>
  </span>
  <span *ngIf="error">
    Loading failed
  </span>
</button>

app.component.ts

import { Component } from '@angular/core';
import { OnInit } from '@angular/core';

import { PokedexService } from './pokedex.service';

import { Pokemon } from './pokemon';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  pokemon: Pokemon[] = [];
  isLoading: boolean = false;
  error: boolean = false;

  constructor(private pokedexService: PokedexService) {}

  ngOnInit() {
    // Loads the initial data.
    this.loadMore();
  }

  loadMore() {
    this.isLoading = true;

    // User the Pokedex service
    // to load the next 9 Pokemon.
    this.pokedexService.getPokemon(this.pokemon.length, 9)
      .then(pokemon => {
        pokemon = pokemon.map(p => {
          p.imageLoaded = false;
          return p;
        });
        this.pokemon = this.pokemon.concat(pokemon);
        this.isLoading = false;
        this.error = false;
      })
      .catch( () => {
        this.error = true;
        this.isLoading = false;
      });
  }
}

I've called my map function's callback with a parameter for the current item in the array I'm mapping and the index of that item, and then included formal parameters for both in the function definition of getTypes, so I'm not sure where the error is coming from or how to resolve it. Any help in clearing this up is greatly appreciated.

2 Answers 2

2

You aren't defining the parameters p or i.

What you want to do is:

.map((p, i) => getTypes(p, i)); 

passing a function to map that has both p and i defined in it's scope.

In your case you're mapping over the result of another map (which returns an array) so you would want to destructure the array as below:

.map(([p, i]) => getTypes(p, i)); 

Which will take the array and split the variable assignments out for you. The same as doing:

   .map(arr => {
        const p = arr.p;
        const i = arr.i;
        return getTypes(p, i);
    });

but a lot more succinct.

Sign up to request clarification or add additional context in comments.

Comments

1

I think it should be

).map(v => getTypes(v.name, v.id))); // <-- error occurs here

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.