Using ng-repeat with the Pokeapi - angularjs

I'm trying to get the data for two random pokémon from the Pokéapi. I can grab the data fine, but my angular $scope variables are overwriting the first pokémon with the second pokémon, instead of storing both:
$http.get(endPoint)
.then(function(res){
$scope.pokemonName = res.data.name; // only one 'pokemonName' in $scope
});
You can visually see the pokémon being loaded and displayed incorrectly (two identical pokémon instead of two different ones) in this Plunker example.
I could manually declare two separate $scope variables, eg:
$scope.pokemonNameOne;
$scope.pokemonNameTwo;
But I want to use ng-repeat in the HTML markup, like this:
<div class='pokemon' ng-repeat="pokemon in pokemonPair">
<h2 class='name'>{{ pokemonName }}</h2>
<img src='{{ pokemonImage }}' />
<!-- etc -->
</div>
I feel like what I should be doing, is looping through the required data from the API, then pushing it into a new array of my own creation, and then using my new array in combination with ng-repeat in order to display the two random pokémon. However, I'm unsure as to whether this is an overly convoluted solution. Should I really be re-creating the API data in my own array? It feels like that would be reinventing the wheel. However, I'm not sure how else to solve this problem besides 'Don't use ng-repeat', which isn't a route I want to go down if I can help it, as I'm trying to learn Angular.
Should I be pushing the API data into an array of my own making in order to display it correctly, or is there a smarter way to use ng-repeat?

You are replacing the existing variables, instead of pushing it to an array. Do something like this:
function getStats(pokemonIndex){
var pokemon = $scope.pokemonPair[pokemonIndex];
$http.get(pokemon.endPoint)
.then(function(res){
pokemon.pokemonName = res.data.name;
pokemon.pokemonExperience = res.data.base_experience;
pokemon.pokemonImage = res.data.sprites.front_default;
pokemon.pokemonStats = res.data.stats;
console.log("pokemonName = " + pokemon.pokemonName);
});
}
and call it like this:
function populateStats(){
for (var i = 0; i < $scope.pokemonPair.length; i++){
getStats(i);
}
}
See this edited plunker
Also notice that I have changed the pokemonPair property to be an array of objects, to be able to add the properties to it and use the ng-repeat.

Here is a working plunker:
https://plnkr.co/edit/c5seK6wr8rQjMAj5GZA9?p=preview
Just push the response from the api into an array and databind everything from there!
function getStats(endPoint){
$http.get(endPoint)
.then(function(res){
$scope.pokemons.push(res.data);
console.log("pokemonName = " + $scope.pokemonName);
});
}

You have to read about Arrays in JavaScript. Your question doesn't actually related to Angular itself.
$scope.pokemonNames = [];
$http.get(endPoint)
.then(function(res){
var pokemon = {};
pokemon.name = res.data.name;
pokemon.attribute = res.data.attribute;
$scope.pokemonNames.push(pokemon); // then iterate over pokemonNames array in ng-repeat.
});

Related

Using Node (API) to display data in Angular

I am still new to the concept of MEAN Stack and right now i am trying to display a list that I get from the Asana API in a simple website that I made. My issue is that in order to get the list that I need from Asana I use nested functions and I have no clue how to send the result to my frontend.
var callback = function() {console.log("test")};
client.projects.findAll(callback).then(function(projects) {
projects.data.forEach(function(project){
var id = project.id;
var name = project.name;
console.log(name);
});
});
If I run the program I do get the list that I want inside my console and would like to know how to display the list from index.html file. Basically how to send the name variable to the frontend.
You need to insert your values in your $scope, for example:
client.projects.findAll(callback).then(function(projects) {
$scope.projects = projects;
});
and then in your HTML use an ng-repeat to display the values, for example:
<div ng-repeat="project in projects | track by $index>
<span>{{project.value}}</span>
</div>
This way, you'll create a div for every project element inside your array, displaying his property .value (but you can substitute .value with any of your properties) with the brackets notation {{ }}

Is it possible to have ng-repeat append data to existing content instead of replacing?

Let's say I have the following html:
<li ng-repeat="item in items></li>
Everytime the user scrolls to the bottom of the list I'm loading 10 more items and I want to append them to the bottom of the list instead of just replacing the content that was there before.
Is there any way to do this with AngularJS?
you can use splice() function of javascript as:
var firstArr= ["One", "Two", "Tree", "Four"];
var secondArr= ["Five","Six"];
firstArr.splice(firstArr.length+1 , 0, secondArr);
result:
One,Two,Tree,Four,Five,Six
See More Info on splice()
I guess something like this would be what you search
function ItemsController($scope,Items){
$scope.onScroll = function(amount){
Items.getMore(amount).then(function(response){
$scope.items.splice($scope.items.length+1 , 0, response.data);
});
}
}
The solution I ended up using was to use the native javascript concat() function, which merges two arrays. I merged the items already in my scope variable with the new ones the ajax request returned which had the desired effect of appending data, instead of replacing it.
So my ajax request looked something like this:
ajaxCallFetchItems().then(function(items) {
$scope.items = $scope.items.concat(items);
});

AngularJS + Hoodie: How to do a correct data flow?

I would like to combine AngularJS and Hoodie, but I am not sure how to do it the correct way.
Let's say I have a basic AngularJS controller
app.controller("c", function($scope) {
$scope.table = [];
$scope.onAdd = function(newEntry) {
$scope.table.push(newEntry);
};
});
After clicking on e.g.
<button ng-click="onAdd('test');">add</button>
Everything works as expected. But now I want to use Hoodie. Currently I am trying this:
app.controller("c", function($scope) {
$scope.table = [];
$scope.onAdd = function(newEntry) {
$scope.table.push(newEntry);
};
hoodie.store.on('entries:add', $scope.onAdd);
});
and anywhere: hoodie.store.add("entries", tmpObject);
The onAdd() gets called and is inserted into the table array (verified in the developer console), but my html table (via ng-repeat="entry in table") is not updated.
First question: Do you know why? What do I think wrong here?
Second question: What would be a good way to combine Hoodie and AngularJS? Would it be better to $watch on the table and insert items into it and store it via Hoodie after getting a change or the other way around and add a new item to the hoodie.store and then on("entries:add") do some Angular stuff?
Thanks in advance!
Heyho =)
First: If you update data-structure via an 'external' event(in this case hoodie), you need to trigger the Digest-Cycle e.g. $rootScope.$apply();
Second: There is a hoodie-angular-plugin that is written by Elmar and me. That solved the most of your basic tasks. That would be the easiest way in this case.

Parsing JSON inside ng-repeat

Is it possible to parse JSON inside an ng-repeat?
I tried both JSON.parse and angular.fromJson.
<div ng-repeat='x in JSON.parse(element.info)'>
{{x.key}}
</div>
It can be checked here: http://jsfiddle.net/y4qje54o/1/
AngularJS handles all ng-repeat with a $watch module nested and hard coded inside the core. If you try to write an uncorrect ng-repeat it will cause a log error spam, this is due to the "reloading" of the ng-repeat loop.
If you put a JSON parse inside a loop it will cause a huge performance breakdown. From controller you will do it once.
Notice that if the view were generating the data once, then performance will be equal. But you will lose MVC pattern. Take care about it.
Why you don't want to do like this ?
var ngApp = angular.module('ngApp',[]);
var ngCtrl = ngApp.controller('ngCtrl',['$scope', function($scope){
$scope.elements = [];
$scope.element = {};
$scope.element.title = 'first element';
//this comes from DB like this(as string)
$scope.element.info = JSON.parse('[{"key":"value1"},{"key":"value2"}]');
$scope.elements.push($scope.element);
}]);
Check it here: https://jsfiddle.net/y4qje54o/4/
Same results, but I did it using split, slice & indexOf instead of JSON.parse.
Code:
<div ng-repeat="x in temp=angular.equals(temp,element.info.slice(1, -1).split(','))?temp:element.info.slice(1,-1).split(',')">
{{x.slice(x.indexOf(':')+2, -2)}}
</div>

ngRepeat seems to use a random order instead of order given

I have a json containing objects originating from my Symfony controller.
I need to loop over the objects like so
<li data-ng-repeat="course in courses"></li>
In my app controller I do this
$scope.courses = {{ courses | serialize('json', serialization_context().setGroups(['identification', 'courseListing', 'portalOverview'])) | raw }};
The order is okay when I check the scope variable 'courses' with the ng-inspect browser plugin.
Screenshot : http://i.imgur.com/pKy00uo.png
But still the loop seems kinda random. The last object keeps getting placed after the 2nd child.
Any ideas? Need more info, just ask. Thanks!
Okay, so it seems Angular doesn't handle objects too well when given to ng-repeat.
I transformed my object of objects to an array of objects and the objects were rendered in the correct order.
var arrCourses = [];
$.each($scope.courses, function(index, obj){
arrCourses.push(obj);
});
$scope.courses = arrCourses;

Resources