Faud
Faud

Reputation: 471

How to reflesh $scope in Angular in AJAX reponse?

I have AJAX response inside that is deleted object:

request.success(function (data) {
    delete $scope.notifications.system[key];
    $scope.$apply();
});

I have HTML code with block, that would be appear by condition:

<span ng-show="notifications.system.length == 0" ng-cloak>
DELETED
</span>

So, I tried to use $scope.$apply(); in response at once after removing object. But I have got error:

Error: [$rootScope:inprog] http://errors.angularjs.org/1.3.13/$rootScope/inprog?p0=%24digest

How I can reload template when notifications.system.length is equal zero?

Upvotes: 1

Views: 229

Answers (3)

AWolf
AWolf

Reputation: 8970

You could also do the managing of your errors differently. Instead of adding directly to an object you could add the error objects to an array. Deleting can then be done with the following code:

$scope.removeError = function (errorName) {
    angular.forEach($scope.notifications, function (error, index) {
        if (error.hasOwnProperty(errorName)) $scope.notifications.pop(index);
    });
};

Have a look at the demo below and here at jsfiddle.

angular.module('myApp', [])
    .controller('mainController', MainController);

function MainController($http, $scope, $timeout) {

    $scope.notifications = [{
        errorImg: 'failed to load image',
    }//, 
    /*{ // other errors
        //errorJS: 'failed to load js'
    }*/];

    $scope.removeError = function (errorName) {
        angular.forEach($scope.notifications, function (error, index) {
            //console.log(index, error.hasOwnProperty(errorName), $scope.notifications);
            if (error.hasOwnProperty(errorName)) $scope.notifications.pop(index);
            //console.log(index, error.hasOwnProperty(errorName), $scope.notifications);
        });
    };
    $scope.clear = function () {
        $http.jsonp('http://www.mocky.io/v2/556f7ba53db19a8f05f1e555?callback=JSON_CALLBACK')
            .success(function (response) {
            //dummy request
            //console.log(response, $scope.notifications);

            //delete $scope.notifications['errorImg'];
            $scope.removeError('errorImg');
        }) //.bind(this))
    }
}

MainController.$inject = ['$http', '$scope', '$timeout'];
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller='mainController as main'> <pre>{{notifications |json}}</pre>

    <!--<button ng-click="main.show()">Show data</button>
    <ul>
        <li ng-repeat="info in main.data">{{info.test}}</li>
    </ul>-->
    <button ng-click="clear()">clear error</button>
    <ul>
        <li ng-repeat="i in dummy">{{i}}</li>
    </ul>
    <div ng-show="notifications.length == 0">deleted</div>
</div>

Upvotes: 1

Jeffrey A. Gochin
Jeffrey A. Gochin

Reputation: 964

If you choose to use the $scope.$apply() you should wrap everything in a $timeout and call it like this.

request.success(function(resp){
    $timeout(function(){
        $scope.$apply(function(){
            //do stuff here to the scope.
        });
    });
});

Passing in a function reference to $apply will cause it to execute that function then $digest. Seems a bit strange I know, but the reason for this is that AngularJS typically calls $digest in response to user interaction, not necessarily to events like $http.success.

Upvotes: 1

jfadich
jfadich

Reputation: 6348

When you use delete on arrays it doesn't change the length of the array instead it replaces the element in the array with undefined. So your ng-show never changes because the length of the array isn't changing. Use splice instead and the array will shorten and your $scope should update at you expect.

$scope.notifications.system.splice($scope.notifications.system.indexOf(key), 1);

you shouldn't need $scope.$apply() for something like this.

Upvotes: 1

Related Questions