TomOw
TomOw

Reputation: 1341

Can't assign object returned by service to $scope

I'm trying to assign data returned by service to $scope property. Somehow it doesn't work properly. The service method correctly get data via $http.get but then it is not assigned to $scope in the controller.

app.service('StoreService', ['$http', function ($http) {

    this.getStoreNamesService = function () {
        console.log('getStoreNames called');
        $http.get('http://localhost:8080/storys')
            .success(function (response, status) {
                console.log(response);
                return response;
            })
    };
}]);

app.controller('ItemFormController', ['$scope', '$http', '$mdDialog', 'itemService', 'StoreService', function ($scope, $http, $mdDialog, itemService, StoreService) {

    $scope.storeNames = StoreService.getStoreNamesService();
}]);

Printing the response in service gives correct data. But when I'm printing $scope.storeNames it gives me undefined also on the views there is no data.

app.js:

var app = angular.module('BlankApp', ['ngMaterial', 'ngRoute'])
.config(function($mdThemingProvider) {
    $mdThemingProvider.theme('default')
        .primaryPalette('teal')
        .accentPalette('red')
        .warnPalette('red');
});

app.config(function ($routeProvider) {
    $routeProvider
        .when('/addItem', {
            templateUrl: 'templates/addItemForm.html',
            controller: 'ItemFormController'
        })
        .when('/', {
        templateUrl: 'templates/first.html'
        })
        .when('/store', {
            templateUrl: 'templates/itemsInStore.html',
            controller: 'StoreController'
        })
        .when('/item/:itemId', {
            templateUrl: 'templates/itemView.html',
            controller: 'ItemController'
        })
        .otherwise({
            template: '<h1>otherwise template</h1>'
        })
});

The order of script tags:

    <!-- Angular Material requires Angular.js Libraries -->
<script src="js/angular-1.5.8/angular.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular-animate.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular-aria.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular-messages.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular-route.min.js"></script>

<!-- Angular Material Library -->
<script src="js/AngularMaterial/angular-material.js"></script>

<!-- Your application bootstrap  -->


<script src="js/app.js"></script>
<script src="js/service/itemService.js"></script>
<script src="js/service/StoreService.js"></script>
<script src="js/controller/testController.js"></script>
<script src="js/controller/SideNavController.js"></script>
<script src="js/controller/ItemFormController.js"></script>

<script src="js/controller/sampleController.js"></script>
<script src="js/controller/ItemController.js"></script>

Upvotes: 1

Views: 499

Answers (3)

Pankaj Parkar
Pankaj Parkar

Reputation: 136134

Couple of things you were mistaken

  1. You should return the promise object return by $http method from service method getStoreNames.
  2. You should not be passing $scope(context) to service to modify it.
  3. You should use .then function to get value from promise object.

    app.service('StoreService', ['$http', function ($http) {
      this.getStoreNamesService = function () {
        //return promise here
        return $http.get('http://localhost:8080/storys');
      };
    }]);
    

Controller

StoreService.getStoreNamesService($scope).then(function(response){
   $scope.storeNames = response.data;
});

Upvotes: 1

mcrvaz
mcrvaz

Reputation: 659

This should work:

app.service('StoreService', ['$http', function ($http) {

this.getStoreNamesService = function () {
    console.log('getStoreNames called');
    return $http.get('http://localhost:8080/storys').then(
        function success(response, status) {
            console.log(response);
            return response;
        })
    };
}]);

app.controller('ItemFormController', ['$scope', '$http', '$mdDialog', 'itemService', 'StoreService', function ($scope, $http, $mdDialog, itemService, StoreService) {
    StoreService.getStoreNamesService().then(function(result){
        $scope.storeNames = result;
    });
}]);

You can only assign the variable storeNames after the promise is resolved. The way you were doing, the promise was being assigned to the variable.

Also notice that .success() is deprecated. Use .then() instead.

Upvotes: 1

Ryan Jenkin
Ryan Jenkin

Reputation: 924

When using Angular you're better off returning a promise, the $http service returns a promise and you can move the success callback to the scope:

app.service('StoreService', ['$http', function ($http) {
    this.getStoreNamesService = function () {
        return $http.get('http://localhost:8080/storys');
    };
}]);

app.controller('ItemFormController', ['$scope', '$http', '$mdDialog', 'itemService', 'StoreService', function ($scope, $http, $mdDialog, itemService, StoreService) {
    StoreService.getStoreNamesService().then(function (response, status) {
        $scope.storeNames = response.data;
    });
}]);

Or you can create a deferred object which is similar in that a promise is returned, except it just returns the data and not the $http status codes, etc:

app.service('StoreService', ['$http', '$q', function ($http, $q) {
    this.getStoreNamesService = function () {
        var deferred = $q.defer();
        $http.get('http://localhost:8080/storys').then(function(response, status){
            deferred.resolve(response.data);
        });
        return deferred;
    };
}]);

app.controller('ItemFormController', ['$scope', '$http', '$mdDialog', 'itemService', 'StoreService', function ($scope, $http, $mdDialog, itemService, StoreService) {
    StoreService.getStoreNamesService().then(function (data) {
        $scope.storeNames = data;
    });
}]);

See $q

In both cases the scope object should be populated within the controller.

Upvotes: 0

Related Questions