Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PokeAPI + Angular: How to get pokemon's evolution chain

I am an Angular novice and am learning a little by trying to pull the evolution chain for each pokemon using pokeapi but having a difficult time because of deep nesting.

A typical response object is returned like this:

{
  "baby_trigger_item": null,
  "id": 2,
  "chain": {
    "evolution_details": [],
    "evolves_to": [
      {
        "evolution_details": [
          {
            "min_level": 16,
            "min_beauty": null,
            "time_of_day": "",
            "gender": null,
            "relative_physical_stats": null,
            "needs_overworld_rain": false,
            "turn_upside_down": false,
            "item": null,
            "trigger": {
              "url": "http://pokeapi.co/api/v2/evolution-trigger/1/",
              "name": "level-up"
            },
            "known_move_type": null,
            "min_affection": null,
            "party_type": null,
            "trade_species": null,
            "party_species": null,
            "min_happiness": null,
            "held_item": null,
            "known_move": null,
            "location": null
          }
        ],
        "evolves_to": [
          {
            "evolution_details": [
              {
                "min_level": 36,
                "min_beauty": null,
                "time_of_day": "",
                "gender": null,
                "relative_physical_stats": null,
                "needs_overworld_rain": false,
                "turn_upside_down": false,
                "item": null,
                "trigger": {
                  "url": "http://pokeapi.co/api/v2/evolution-trigger/1/",
                  "name": "level-up"
                },
                "known_move_type": null,
                "min_affection": null,
                "party_type": null,
                "trade_species": null,
                "party_species": null,
                "min_happiness": null,
                "held_item": null,
                "known_move": null,
                "location": null
              }
            ],
            "evolves_to": [],
            "is_baby": false,
            "species": {
              "url": "http://pokeapi.co/api/v2/pokemon-species/6/",
              "name": "charizard"
            }
          }
        ],
        "is_baby": false,
        "species": {
          "url": "http://pokeapi.co/api/v2/pokemon-species/5/",
          "name": "charmeleon"
        }
      }
    ],
    "is_baby": false,
    "species": {
      "url": "http://pokeapi.co/api/v2/pokemon-species/4/",
      "name": "charmander"
    }
  }
}

I have to get to evolves_to property, and grab species.name as well as evolution_details.min_level and evolution_details.trigger.name, and evolution_details.item if not null

But as you can see, the evolves_to property, itself contains another evolves_to nested inside, which has another nested inside

This is my sad attempt (after http.get) and I'm just stuck now.

var evoObject = response.data;

function loopEvo(obj){
    angular.forEach(obj, function(value, key, object){
        if (key == 'evolves_to' && value != []) {
            //from here I can get top level data, but...
        }
    });
}

loopEvo(evoObject.chain);

I don't know how to recursively dive into objects and continually grab data, can anyone provide any help? I would love to use this as a great learning opportunity in traversing complex json objects.

like image 468
coderpolarbear Avatar asked Aug 24 '16 00:08

coderpolarbear


People also ask

Is it possible to make an evolution chain using angular?

You could always just avoid using Angular and stick with plain JS to build out your evolution chain... try giving this a go, it was based on your angular for loop. This should leave you with an array ( evoChain) of the objects containing the data you are looking for ordered from first evolution at 0 index to last evolution at the last index.

Why can't I See my Pokemon's evolution chain on the endpoint?

On the evolution endpoint, the evolution id's do not match the pokemon id's making it near impossible to show an evolution chain for the pokemon. It would be awesome to have those id's match up.

How to get the evolution chain url of a Pokemon?

But the evolution API needs the id of the base Pokemon, for example in order to get the evolution chain of Charmeleon we need to provide the evolution endpoint id of Charmander. Instead, we can directly get the evolution chain URL from species endpoint, so will make a call to species endpoint later will call the evolution endpoint.

What is pokeapi and why should I use it?

The PokeAPI has everything; Pokemons, their attacks, types, evolutions, spices and everything on a simple HTTP’s GET. Fun fact it was originally a weekend project of Paul Hallett the guy behind this amazing tool, so keep a watch on your weekend projects. The PokeAPI usage is straight forward and comes with nicely written documentation.


2 Answers

You could always just avoid using Angular and stick with plain JS to build out your evolution chain... try giving this a go, it was based on your angular for loop. This should leave you with an array (evoChain) of the objects containing the data you are looking for ordered from first evolution at 0 index to last evolution at the last index.

var evoChain = [];
var evoData = response.data.chain;

do {
  var evoDetails = evoData['evolution_details'][0];

  evoChain.push({
    "species_name": evoData.species.name,
    "min_level": !evoDetails ? 1 : evoDetails.min_level,
    "trigger_name": !evoDetails ? null : evoDetails.trigger.name,
    "item": !evoDetails ? null : evoDetails.item
  });

  evoData = evoData['evolves_to'][0];
} while (!!evoData && evoData.hasOwnProperty('evolves_to'));

In your sample case above the resulting array should appear as follows:

[{
    "species_name": "charmander",
    "min_level": 1,
    "trigger_name": null,
    "item": null
}, {
    "species_name": "charmeleon",
    "min_level": 16,
    "trigger_name": "level-up",
    "item": null
}, {
    "species_name": "charizard",
    "min_level": 36,
    "trigger_name": "level-up",
    "item": null
}]
like image 185
Ryan Avatar answered Nov 10 '22 09:11

Ryan


The approved answer above does not work if there are multiple evolutions such as Eevee or Snorunt. That will only return the first evolution e.g. Vaporeon

The following checks number of evolutions and runs through them all.

let evoChain = [];
let evoData = chain.chain;

do {
  let numberOfEvolutions = evoData['evolves_to'].length;  

  evoChain.push({
    "species_name": evoData .species.name,
    "min_level": !evoData ? 1 : evoData .min_level,
    "trigger_name": !evoData ? null : evoData .trigger.name,
    "item": !evoData ? null : evoData .item
  });

  if(numberOfEvolutions > 1) {
    for (let i = 1;i < numberOfEvolutions; i++) { 
      evoChain.push({
        "species_name": evoData.evolves_to[i].species.name,
        "min_level": !evoData.evolves_to[i]? 1 : evoData.evolves_to[i].min_level,
        "trigger_name": !evoData.evolves_to[i]? null : evoData.evolves_to[i].trigger.name,
        "item": !evoData.evolves_to[i]? null : evoData.evolves_to[i].item
     });
    }
  }        

  evoData = evoData['evolves_to'][0];

} while (!!evoData && evoData.hasOwnProperty('evolves_to'));

return evoChain;
like image 24
brandudno Avatar answered Nov 10 '22 10:11

brandudno