'$scope variable getting updated before getting displayed from api requests

I am attempting to get JSON Data Array using API and Display the same on Webpage. The problem I am encountering is the Element in the Webpage is being loaded as part of a loop multiple times sending multiple API requests. The API response is stored in a $scope variable and since the requests are too many, I think most recent api response ends up displaying... Is there a way to return the API response back through the function. I will explain in detail below:

Following is the code which is running as part of a loop. When the <dynamic> element is loaded, executeRequest() function gets fired on loading due to ng-init. The parameters for the API to return data are passed through this function. executeRequest() function is part of the angular module.

<dynamic ng-class="getProperties(object.id+barelement.id+containerelement.id+ddelement.id+ddcbelement.id+rowelement.id+rowcbelement.id+rowelement2.id,'linkedto','ng-class')" ng-if="object.type === 'dynamiccontentblock' || barelement.type === 'object' || containerelement.type === 'object' || ddelement.type === 'object' || ddcbelement.type === 'object' || rowelement.type === 'object' || rowcbelement.type === 'object' || rowelement2.type === 'object'" ng-init="executeRequest(getProperties(object.id+barelement.id+containerelement.id+ddelement.id+ddcbelement.id+rowelement.id+rowcbelement.id+rowelement2.id,'property','executeOnInit'));">
        <dynamicMainBlock ng-repeat="apiItem in apiData">        
            <dynamicContentBlock ng-repeat="dcbelement in elements | filter: {of: 'object'}: true | filter: {of_id: barelement.id}: true | orderBy:'loadpriority'" ng-include="dcbelement.path"></dynamicContentBlock>
        </dynamicMainBlock>
</dynamic>

Inside the executeRequest() function another function getDataFmAPI() gets fired to deal with the API Request and Response. Parameters are passed to this function. Once the getDataFmAPI() function gets executed the response is stored in $scope.apiData . We then loop through the response in the <dynamic> element displayed above.

The problem using this method is when the <dynamic> element is loaded multiple times, executeRequest() and hence getDataFmAPI() gets fired with each loading. The Data obtained from the previous API request gets replaced with the most recent one. Ideally I need multiple <dynamic> elements to be displayed with different API Request and Responses. However, this is not happening. What is happening is all the <dynamic> elements are displaying Data which came from the last request. I believe this is because of the $scope.apiData variable not getting updated in timely manner with the loading of the <dynamic> element in the front end.

angular.module('myApp', []).controller("myCtrl", function($scope,$http){
    $scope.executeRequest = function(jsonString){ 
        jsonObject = JSON.parse(jsonString);         
        switch(jsonObject.functionToRun){
            case "toggleObject":{
                $scope.toggleObject(jsonObject.functionParameters.objID);
                break;
            }
                
            case "getDataFmAPI":{
                $scope.getDataFmAPI(jsonObject.functionParameters);
                break;
            }
        }
    };
        
    $scope.getDataFmAPI = function(jsonObject){
        var httpString = '';
        httpString += $scope.wslink+"content/plugins/api.php?";
        httpString += (jsonObject.table != undefined)?'table='+jsonObject.table:'';
        httpString += (jsonObject.where != undefined)?'&where='+jsonObject.where:'';
        httpString += (jsonObject.primary != undefined)?'&primary='+jsonObject.primary:'';
        httpString += (jsonObject.orderby != undefined)?'&orderby='+jsonObject.orderby:'';
        httpString += (jsonObject.fetch != undefined)?'&fetch='+jsonObject.fetch:'';
        httpString += (jsonObject.user != undefined)?'&user='+jsonObject.user:'';
        httpString += (jsonObject.key != undefined)?'&key='+jsonObject.key:'';        
            
        $http.get(httpString).then(function(response){            
            $scope.apiData = response.data;
            console.log(response.data);
        });
    };
});

Instead of storing the API response data in $scope.apiData variable is there a way to return the same through the function. Similar to below:-

$scope.executeRequest = function(jsonString){ 
        jsonObject = JSON.parse(jsonString);         
        switch(jsonObject.functionToRun){
            case "toggleObject":{
                $scope.toggleObject(jsonObject.functionParameters.objID);
                break;
            }
                
            case "getDataFmAPI":{
                return $scope.getDataFmAPI(jsonObject.functionParameters);
                break;
            }
        }
    };
    $scope.toggleObject = function(objID=''){
        if(objID != '')
            if(angular.element(document.querySelectorAll("."+objID+".w3-hide")).length > 0){            
                angular.element(document.querySelectorAll("."+objID+".w3-hide")).addClass("w3-show");
                angular.element(document.querySelectorAll("."+objID+".w3-hide")).removeClass("w3-hide");
            } else {
                angular.element(document.querySelectorAll("."+objID+".w3-show")).addClass("w3-hide");
                angular.element(document.querySelectorAll("."+objID+".w3-show")).removeClass("w3-show");
            };
    };    
    $scope.getDataFmAPI = function(jsonObject){
        var httpString = '';
        httpString += $scope.wslink+"content/plugins/api.php?";
        httpString += (jsonObject.table != undefined)?'table='+jsonObject.table:'';
        httpString += (jsonObject.where != undefined)?'&where='+jsonObject.where:'';
        httpString += (jsonObject.primary != undefined)?'&primary='+jsonObject.primary:'';
        httpString += (jsonObject.orderby != undefined)?'&orderby='+jsonObject.orderby:'';
        httpString += (jsonObject.fetch != undefined)?'&fetch='+jsonObject.fetch:'';
        httpString += (jsonObject.user != undefined)?'&user='+jsonObject.user:'';
        httpString += (jsonObject.key != undefined)?'&key='+jsonObject.key:'';        
            
        return $http.get(httpString).then(function(response){            
            //$scope.apiData = response.data;
            //console.log(response.data);
            return response.data;
        });
    };

We can then store the response in a variable in the <dynamic> element and access it from there.

<dynamic ng-class="getProperties(object.id+barelement.id+containerelement.id+ddelement.id+ddcbelement.id+rowelement.id+rowcbelement.id+rowelement2.id,'linkedto','ng-class')" ng-if="object.type === 'dynamiccontentblock' || barelement.type === 'object' || containerelement.type === 'object' || ddelement.type === 'object' || ddcbelement.type === 'object' || rowelement.type === 'object' || rowcbelement.type === 'object' || rowelement2.type === 'object'" ng-init="responseData = executeRequest(getProperties(object.id+barelement.id+containerelement.id+ddelement.id+ddcbelement.id+rowelement.id+rowcbelement.id+rowelement2.id,'property','executeOnInit'));">
    <dynamicMainBlock ng-repeat="apiItem in responseData">        
        <dynamicContentBlock ng-repeat="dcbelement in elements | filter: {of: 'object'}: true | filter: {of_id: barelement.id}: true | orderBy:'loadpriority'" ng-include="dcbelement.path"></dynamicContentBlock>
    </dynamicMainBlock>
</dynamic>

Basically I am looking for a way to return API response data through the function instead of assigning it to $scope variable. When I try to return it through the function below is how the console.log displays. Not sure how to access the data from below:

f$$state: status: 1value: Array(10)0: {nid: 2, shortname: 'Property for Sale', longname: 'Property for Sale', description: null, path: 'classifieds/property-for-sale/', …}1: {nid: 3, shortname: 'Property for Rent', longname: 'Property for Rent', description: null, path: 'classifieds/property-for-rent/', …}2: {nid: 4, shortname: 'Motors', longname: 'Motors', description: null, path: 'classifieds/motors/', …}3: {nid: 5, shortname: 'Jobs', longname: 'Jobs', description: null, path: 'classifieds/jobs/', …}4: {nid: 6, shortname: 'Community', longname: 'Community', description: null, path: 'classifieds/community/', …}5: {nid: 7, shortname: 'Business Commercial & Industrial', longname: 'Business Commercial & Industrial', description: null, path: 'classifieds/business-commercial-and-industrial/', …}6: {nid: 8, shortname: 'Electronics & Communication', longname: 'Electronics & Communication', description: null, path: 'classifieds/electronics-and-communication/', …}7: {nid: 9, shortname: 'Furniture', longname: 'Furniture', description: null, path: 'classifieds/furniture/', …}8: {nid: 10, shortname: 'Education Training & Certification', longname: 'Education Training & Certification', description: null, path: 'classifieds/education-training-and-certification/', …}9: {nid: 11, shortname: 'Clothing & Apparels', longname: 'Clothing & Apparels', description: null, path: 'classifieds/clothing-and-apparels/', …}length: 10[[Prototype]]: Array(0)[[Prototype]]: Object[[Prototype]]: Object
(index):547 f$$state: status: 1value: Array(13)0: {nid: 12, shortname: 'Apartment / Flat for Sale', longname: 'Apartment / Flat for Sale under Property for Sale', description: null, path: 'classifieds/property-for-sale/apartment-or-flat-for-sale/', …}1: {nid: 13, shortname: 'Residential Units for Sale', longname: 'Residential Units for Sale under Property for Sale', description: null, path: 'classifieds/property-for-sale/residential-units-for-sale/', …}2: {nid: 14, shortname: 'Commercial Units for Sale', longname: 'Commercial Units for Sale under Property for Sale', description: null, path: 'classifieds/property-for-sale/commercial-units-for-sale/', …}3: {nid: 15, shortname: 'Villa for Sale', longname: 'Villa for Sale under Property for Sale', description: null, path: 'classifieds/property-for-sale/villa-for-sale/', …}4: {nid: 16, shortname: 'Land for Sale', longname: 'Land for Sale under Property for Sale', description: null, path: 'classifieds/property-for-sale/land-for-sale/', …}5: {nid: 17, shortname: 'Townhouse for Sale', longname: 'Townhouse for Sale under Property for Sale', description: null, path: 'classifieds/property-for-sale/townhouse-for-sale/', …}6: {nid: 18, shortname: 'Penthouse for Sale', longname: 'Penthouse for Sale under Property for Sale', description: null, path: 'classifieds/property-for-sale/penthouse-for-sale/', …}7: {nid: 19, shortname: 'Residential Building for Sale', longname: 'Residential Building for Sale under Property for Sale', description: null, path: 'classifieds/property-for-sale/residential-building-for-sale/', …}8: {nid: 20, shortname: 'Residential Floor for Sale', longname: 'Residential Floor for Sale under Property for Sale', description: null, path: 'classifieds/property-for-sale/residential-floor-for-sale/', …}9: {nid: 21, shortname: 'Commercial Building for Sale', longname: 'Commercial Building for Sale under Property for Sale', description: null, path: 'classifieds/property-for-sale/commercial-building-for-sale/', …}10: {nid: 22, shortname: 'Commercial Floor for Sale', longname: 'Commercial Floor for Sale under Property for Sale', description: null, path: 'classifieds/property-for-sale/commercial-floor-for-sale/', …}11: {nid: 23, shortname: 'Shop for Sale', longname: 'Shop for Sale under Property for Sale', description: null, path: 'classifieds/property-for-sale/shop-for-sale/', …}12: {nid: 24, shortname: 'Office for Sale', longname: 'Office for Sale under Property for Sale', description: null, path: 'classifieds/property-for-sale/office-for-sale/', …}length: 13[[Prototype]]: Array(0)[[Prototype]]: Object[[Prototype]]: Object

Any help in this will be highly appreciated. Thanks to all in advance.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source