Search code examples
javascriptangularjsangularjs-scope

Cannot get the current value returned by $http.get when setting $scope variable, only the previous value


I have an angular view that has a table of rows consisting of a select list and an text box. When a select list index is changed, I need to update the corresponding text box on the same row with a lookup value from the database. I am using ng-Change on the select list to call a $scope function that utilizes $http.get to make the call through an ActionMethod. I have tried this in a million ways, and finally was able to extract a value from the $http.get function by assigning it to a scope variable, but I only ever get the value of the previous lookup triggered by the selected index change, not the current one. How can I get a value real-time? I understand it is asynchronous, so I know the nature of the problem. How do I work around it? Current state of my .js:

$scope.EntityId = null; 
$scope.EntityNameChanged = function (item, block) {
    for (var i = 0; i < block.length; i++)
    {
        if (item.Value == block[i].Name.Value) {
            $scope.GetEntityId(item.Value);
            block[i].Id = $scope.EntityId;
        }
    } 
} 
$scope.GetEntityId = function(name) {
    $http.get("EntityId", { params: { EntityName: name } }).then(function success(response) {
        $scope.EntityId = response.data[0].Value;
    }); 
};

Solution

  • The GetEntityID function should return a promise

    function GetEntityId(name) {
        //save httpPromise
        var p = $http.get("EntityId", { params: { EntityName: name } });
    
        //return derived promise
        return p.then(function onSuccess(response) {
            //return chained data
            return response.data[0].Value;
        }); 
    };
    

    Then use an IIFE in the for loop.

    $scope.EntityNameChanged = function (item, block) {
        for (var i = 0; i < block.length; i++) {
            //USE IIFE to hold value of i
            (function IIFE(i) {
                if (item.Value == block[i].Name.Value) {
                    //save promise
                    var p = GetEntityId(item.Value);
                    //extract value from promise
                    p.then(function onSuccess(Value) {
                         block[i].Id = Value;
                    });
                }
            })(i); 
        }
    } 
    

    Because the onSuccess function gets invoked asynchronously after the for loop completes, an IIFE closure is necessary to preserve the value of i until after the data is returned from the server.