1

What I am doing is hitting an API and getting back an array of characters. Each character has a set of items in their inventory. When I first get the info, it only gives me the item's ID. I then have to use that ID and make another API call to get info related to that item so I can properly get the name and stats from it.

<div class="gwapi_content row" ng-repeat="character in characters" ng-if="character.profession == 'Warrior'">

  <div class="character-header">
    <h3>{{character.name | uppercase}} <img src="img/{{character.profession}}_icon.png" alt=""></h3>
    <h5 class="subheader">{{character.race}} {{character.profession}}</h5>
  </div>

  <div class="column photo" style="background-image: url('../img/{{character.name}}.jpg')">
    <img src="img/{{character.profession}}_icon.png" alt="">
  </div>

  <div class="column info">
    <div class="panel-content">
      <ul>
        <li>NAME: {{character.name}}</li>
        <li>CLASS: {{character.profession}}</li>
        <li>
          LEVEL: {{character.level}}
        </li>
        <li>
          Race: {{character.race}}
        </li>
        <li>
          Gender: {{character.gender}}
        </li>
        <li>Birthday: {{character.created | date: 'MMMM dd, yyyy'}}</li>
        <li>Deaths: {{character.deaths}}</li>
      </ul>
    </div>
  </div>

  <div class="column equipment">
    <div class="panel-content">
      <ul class="">
        <li>
          <ul class="li equipment-list">
            <li ng-repeat="equip in character.equipment" ng-init="getEquipmentDetails(equip.id)">
              <span>
                {{equip.id}} {{details.name}}
              </span>
            </li>
          </ul>
        </li>
      </ul>
    </div>
  </div>

  <div class="clear"></div>
</div>

As you can see I am calling the item function while getting the array of the list of items: ng-repeat="equip in character.equipment" ng-init="getEquipmentDetails(equip.id)"

This is where I have my problem. Whenever I make this API call with the ID all the names just get replaced to the last one it loaded. As seen in the image below.

Item ID's with names being replaced by last loaded

I'm sure I am doing this portion wrong, but I've not experienced this before so I am unsure how to approach this. I need to end up with each character getting their own respective list of items, with the items respective name and stats.

Here is the javascript:

$scope.getAccount = function(){

$http.get('https://api.guildwars2.com/v2/characters?access_token='+access_token+'&page=0')
.success(function(response, status, headers, config){
  // console.log(response);
  $scope.characters = response;
})
.error(function(data, status, headers, config) {
  console.log("Error retreiving data");
  // console.log(data + '\n' + status + '\n' + headers +'\n' + config);
});
};

$scope.getAccount();

$scope.getEquipmentDetails = function(id){


$http.get('https://api.guildwars2.com/v1/item_details.json?item_id=' + i)
.success(function(response, status, headers, config){

  $scope.details = response;

})
.error(function(response, status, headers, config){

  console.log('No info');

});

};
2
  • 2
    Not much of an angular dev, but i feel like you should be doing that request in your controller to fetch all the equipment details. Then set that as your scope, and iterate throught it in the template. Commented Jul 29, 2015 at 12:41
  • The only appropriate use of ngInit is for aliasing special properties of ngRepeat, as seen in the demo below. Besides this case, you should use controllers rather than ngInit to initialize values on a scope. docs.angularjs.org/api/ng/directive/ngInit Commented Jul 29, 2015 at 12:57

1 Answer 1

2

The root of your problem is that you are setting a single variable for the equipment details, so that single variable's content is being bound to the template. You are probably getting all of the different detail data but the last one to finish will always be the one displayed because it will set the value of $scope.details and refresh the template and ALL uses of {{details.name}} will get the new value.

That's actually how it is supposed to work.

What would be better is to pass just equip to your function and then add the details to the equip in your function. So something like:

ng-init="getEquipmentDetails(equip)"

And then change your function to:

$scope.getEquipmentDetails = function(equipment){

$http.get('https://api.guildwars2.com/v1/item_details.json?item_id=' + equipment.id)
.success(function(response, status, headers, config){
  equipment.details = response;
})
.error(function(response, status, headers, config){
  console.log('No info');
    });
}

And then change your template to use:

{{equip.details.name}}

That will modify each equipment item in the character.equipment array rather than the single variable in your controller's scope.

I would also suggest not using ng-init in this way, it isn't really the intent of the directive.

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

3 Comments

Thanks for the advice. I'm a new AngularJS learner, so how would you recommend I avoid using ng-init in that way? Should I make the call immediately after making my character call in the API? Also after trying the code, it resulted in the same response: All names being replaced.
There are several ways to go about it but the one that is most simple would just be to do a $scope.characters.forEach(function(character){ character.equipment.forEach(equip){ getEquipmentDetails(equip); } } immediately after you set $scope.characters.
I realized your code worked. I had made a mistake when rewriting it, but I am going to take the approach and bring this into the controller so as to avoid bad practice.

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.