371273
371273

Reputation: 5436

AngularJS promise doesn't update scope set to single item in array

I have two controllers:

function AppCtrl($scope, $dataService) {
    $scope.projects = $dataService.data.projects;
}

function ProjectCtrl($scope, $route, $q) {
    //Getting the current project from the array of projects
    $scope.project = $scope.projects.then(function(projects) {
        for(i in projects) {
            if(projects[i]._id == $route.current.params.projectId) {
                return projects[i];
            }
        }
    });
}

And a service that I made:

app.service('$dataService', function($q, $http, $location) {
    var dataService = this; //Provides access 'this' inside functions below

    var projectsDeferred = $q.defer();
    $http.get('/api').success(function(data, status, headers, config) {
        projectsDeferred.resolve(data.projects);
    }).error(function(err) {
        projectsDeferred.reject(err);
    });

    this.data = {projects: projectsDeferred.promise};


    this.updateProject = function(project, updateData) {
        $http.put('/api/projects/' + project._id, updateData).success(function(newData, status, headers, config) {
            for(i in dataService.data.projects.$$v) {
                if(project == dataService.data.projects.$$v[i]) {
                    dataService.data.projects.$$v[i] = newData;
                }
            }
        }).error(function(data, status, headers, config) {});
    };
});

When the user performs a certain action, I will call $dataService.updateProject() which will send data to the server, and if successful, the server will respond with the updated data, which will then set the matching project in the array to the new value. I can confirm that $scope.projects in AppCtrl receives the update, and the scope is automatically updated when new data comes back from the server. However, $scope.project in ProjectCtrl never gets the update and it is stuck with the old data. I guess this is because it's only a single object in the array? I've tried calling $rootScope.$apply() after I set the data in the updateProject() function, but it gives me the error that a $digest is already in progress. What do I need to do to make sure that $scope.project (the single item) gets updated? Do I need to make a new promise for that? Can someone show an example of how it is done?

Upvotes: 1

Views: 994

Answers (1)

bmleite
bmleite

Reputation: 26880

The problem is basically what you said, the $scope.project is a reference to an Object inside the $scope.projects Array, so it will hold its reference until the Controller is destroyed.

Try watching for changes on $scope.projects and (re)assign the $scope.project when it happens:

function ProjectCtrl($scope, $route, $q) {        
    $scope.$watch('projects', function(projects) {
       for (i in projects) {
            if(projects[i]._id == $route.current.params.projectId) {
                $scope.project = projects[i];
            }
        }
    }, true);
}

Upvotes: 4

Related Questions