Question

Here's my setup, I have a backend API running on Tomcat and built in Spring and the frontend in Angular JS, data is passed back and forth via JSON. All operations on the backend API were tested with the REST console and the Angular app as well. The app is a CRUD for Teams which are described by an id, a name and a team rating , for example :

[{"id":69,"name":"test","rating":5},{"id":70,"name":"test 2","rating":6}]

I noticed that my views aren't updated after I add a new team or delete a new team even though the POST or DELETE requests executed successfully and the changes are reflected in the database (MySQL).

I'm not sure if I need to manually invoke $scope.$apply or if I need to implement promises to make the app work.

app.js

var teamApp = angular.module('teamApp',[
    'ngRoute',
    'teamControllers',
    'teamServices'
]);

teamApp.config(['$httpProvider', function($httpProvider) {
    delete $httpProvider.defaults.headers.common["X-Requested-With"];
}]);

teamApp.config(['$routeProvider',
    function($routeProvider) {
        $routeProvider.
            when('/teams', {
                templateUrl: 'views/team-list.html',
                controller: 'teamController'
            }).
            when('/team/:teamId', {
                templateUrl: 'views/team-detail.html',
                controller: 'teamDetailController'
            }).
            when('/teams/create', {
                templateUrl: 'views/team-create.html',
                controller: 'teamCreateController'
            }).
            otherwise({
                redirectTo: '/teams'
            });
    }]);

controllers.js

var teamControllers = angular.module('teamControllers', []);

teamControllers.controller('teamController',
    ['$scope', 'Teams', 'Teams', '$location',
    function($scope, Teams, Team, $location) {

    $scope.viewTeam = function(teamId) {
        $location.path('/team/'+teamId);
    };

    $scope.createTeam = function () {
        $location.path('/teams/create');
    };

    $scope.teams = Teams.query();
    $scope.teams.$promise.then(function(result){
        console.log('Success ' + result);
        $scope.teams = result;
    });

}]);

teamControllers.controller('teamDetailController',
    ['$scope', '$routeParams', 'Team', '$location',
    function($scope, $routeParams, Team, $location){

    $scope.cancel = function() {
        $location.path('/teams');
    };

    $scope.deleteTeam = function(teamId) {
        Team.delete({teamId: teamId});
        $location.path('/teams');
    };

    $scope.team = Team.show({teamId: $routeParams.teamId});

}]);

teamControllers.controller('teamCreateController',
    ['$scope', 'Teams', '$location',
    function($scope, Teams, $location){

    $scope.createTeam = function() {
        Teams.create($scope.team);
        $location.path('/teams');
    }

    $scope.cancel = function() {
        $location.path('/teams');
    };

}]);

services.js

var teamServices = angular.module('teamServices', ['ngResource']);

teamServices.factory('Teams', ['$resource',
    function($resource){
        return $resource('http://localhost:8080/api/teams', {}, {
            query: {method:'GET', isArray:true},
            create: {method:'POST'}
        });
    }]);

teamServices.factory('Team', ['$resource',
    function($resource){
        return $resource('http://localhost:8080/api/team/:teamId', {}, {
            show : {
                method:'GET'
            },
            delete : {
                method:'DELETE'
            }
        });
    }]);

index.html

<html lang="en" ng-app="teamApp">

    <head>

        <link rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/themes/smoothness/jquery-ui.css" />
        <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
        <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap-theme.min.css">

        <style>
            body {
                padding-top: 60px;
            }
            @media (max-width: 980px) {
                body {
                    padding-top: 0;
                }
            }
        </style>

        <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
        <script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/jquery-ui.min.js"></script>
        <script src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
        <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js"></script>
        <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular-route.min.js"></script>
        <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular-resource.min.js"></script>

        <script src="js/app.js"></script>
        <script src="js/controllers.js"></script>
        <script src="js/services.js"></script>

    </head>

    <body>

        <div ng-view></div>

    </body>

</html>

Solution

In the controllers.js I've changed the createTeam and deleteTeam calls and used promises, for example:

Before:

    $scope.createTeam = function() {
        Teams.create($scope.team);
        $location.path('/teams');
    }

After:

$scope.createTeam = function() {
    Teams.create($scope.team).$promise.then(
        function(result){
            console.log('Success' + result);
            $location.path('/teams');
        },
        function(error){
            alert(error);
            console.log(error);
        }
    );
}
Was it helpful?

Solution

Now I read a bit more carefully, hope I'm not wrong, see this about promises. I think that you are not waiting for the DELETE or POST request to complete, and you are going on the teams page where you make a GET query to list all the teams, You should redirect on the teams page on the success return of the POST/DELETE or you should chain your request so the GET runs AFTER the POST/DELETE, because, ATM, it appears that you are trying to make the second CALL before the first one is DONE.

You have a promise on the TEAMS QUERY, but you don't have one on the POST/DELETE, as far as I can tell.

I might be wrong though, check this out nonetheless.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top