0

I'm trying to construct a translated message by looping over an array of objects and then adding a new "message" property to that object containing the translated string. I see the correct message output while inside $translate.then(); but when I assign the message to the object it is undefined. What is the correct way to resolve the promise returned from $translate.then() and assign it to the "message" property?

//items.controller.js

function getItems() {
    return itemsFactory.getItems()
    .then(function (response) {
        vm.items = initItemsList(response.activities);
    });
}

function initItemsList(itemsList) {
    for (var i = 0; i < itemsList.length; i++){
        var activityType = itemsList[i].activityType;

        switch (activityType){
            case "HISTORY": {
                var itemName = itemsList[i].item.itemName;
                var itemVersion = itemsList[i].item.itemVersion;
                $translate('activity.'+activityType, { itemname: itemName, itemversion: itemVersion }).then(function(content){
                    vm.itemContent = content;
                    console.log(vm.itemContent); // correct message displayed.
                });
                break;
            }
            default: {
                break;
            }
        }
        itemsList[i].message = vm.itemContent; // undefined
    }
    return itemsList;
}

// translation.json

"activity : {
    "HISTORY" : "History for {{ itemname }} {{ itemversion }}."
    } 
neridaj
  • 2,143
  • 9
  • 31
  • 62
  • Could it be that the last assignments appends before the promise resolves? What about moving the `itemList[i].message = ...` inside of the `.then( )...` part? – Vegar Apr 14 '15 at 21:40
  • I tried this but only the last item's message gets set corrrectly. I can see all the messages printed to the console inside $translate.then() but only the last item's message is set. – neridaj Apr 14 '15 at 22:09
  • @neridaj read http://stackoverflow.com/q/23667086/1048572 – Bergi Apr 14 '15 at 22:50
  • Using the deferred method results in the same behavior i.e., only the last item of the loop is available inside $translate.then(). The loop is completing before the assignment happens, so itemList[i] is always the last item. I can see that inside $translate.then() that each translated message is assigned to the last item of the loop. – neridaj Apr 14 '15 at 23:48

2 Answers2

0

As @Vegar correctly states, the code inside then is executed after the assignment so moving the assignment inside then function will take care of the problem. However, your itemsList will be returned from the function before all the translations are done so you will need to return a promise that resolves when all translations are done:

function initItemsList(itemsList) {
   var allTranslations = [];

   for (var i = 0; i < itemsList.length; i++){
      var activityType = itemsList[i].activityType;
      switch (activityType){
        case "HISTORY": {
            var itemName = itemsList[i].item.itemName;
            var itemVersion = itemsList[i].item.itemVersion;
              allTranslations.push($translate('activity.'+activityType, { itemname: itemName, itemversion: itemVersion }).then(function(content){
                vm.itemContent = content;
                itemsList[i].message = vm.itemContent;
            }));
            break;
        }
        default: {
              break;
           }
       }
   }
   return  $q.all(allTranslations);
}

The caller of your function will have to do like:

initItemList(itemList).then(function(translatedList){
     //Do stuff with translated list
});
Christian
  • 7,433
  • 4
  • 36
  • 61
  • [Why use a deferred?](http://stackoverflow.com/q/23803743/1048572) Also, `$q.all` does not take a callback. – Bergi Apr 14 '15 at 22:48
0

Promises are always resolved asynchronously. So the statement

itemsList[i].message = vm.itemContent;

, which is executed right after the switch, is executed before the callback passed to the $translate promise. Just move the statement to the callback:

$translate('activity.'+activityType, { itemname: itemName, itemversion: itemVersion }).then(function(content){
                vm.itemContent = content;
                console.log(vm.itemContent);
                itemsList[i].message = vm.itemContent;
            });
JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255