Nuno Bentes
Nuno Bentes

Reputation: 1517

Angular Service - Pass $http data to scope

I´m trying to create an angular function inside on Service to return acess data via $http and then return to a desired scope.

So my service it something like this;

app.service('agrService', function ($http) {

    this.testinho = function(){
        return "teste";
    }

    this.bannerSlides = function(){

        var dataUrl = "data/banner-rotator.json";

        // Simple GET request example :
        $http({
            method: 'GET',
            dataType: "json",
            url: dataUrl
        })
        .success( function(data, status, headers, config) {

            // this callback will be called asynchronously
            // when the response is available

            //console.log(data);
            return data;

        }).error( function(data, status, headers, config) {

            // called asynchronously if an error occurs
            // or server returns response with an error status.
            alert("Niente, Nada, Caput");
        });

    }

})

Then i want to associate the returned data to a scope inside of my main App controller... like this:

app.controller('AppCtrl', function($scope, $http, agrService) {
    $scope.slides = agrService.bannerSlides();
})

Then in my template i want to loop the data like this:

<div ng-repeat="slide in slides">
    <div class="box" style="background: url('{{ slide.url }}') no-repeat center;"></div>
</div>

The problem is that the data it´s only available on success and i don´t know how to pass it to my scope slides!!!!!

What i´m doing wrong?

Many thanks in advance

Upvotes: 4

Views: 3573

Answers (4)

Kalhan.Toress
Kalhan.Toress

Reputation: 21901

Use this in your service

.... 
this.bannerSlides = function(){
     var dataUrl = "data/banner-rotator.json";
     return $http({
        method: 'GET',
        dataType: "json",
        url: dataUrl
    });
};  
...

And this in your controller

agrService.bannerSlides().then(function(data) {
    $scope.slides = data;
}, function() {
   //error
});

you don't need $q promise inside the service because the $http is returning a promise by default

The $http service is a function which takes a single argument — a configuration object — that is
used to generate an HTTP request and returns a promise with two $http specific methods: success and error

reference

here is a Fiddle Demo

Upvotes: 1

JLRishe
JLRishe

Reputation: 101758

bannerSlides() doesn't return the values you need right away. It returns a promise that you can use to obtain the value at a later time.

In your service you can use the .then() method of the promise that $http() produces to do initial handling of the result:

 return $http({
    method: 'GET',
    dataType: "json",
    url: dataUrl
 }).then(function (data) {
     // inspect/modify the received data and pass it onward
     return data.data;
 }, function (error) {
     // inspect/modify the data and throw a new error or return data
     throw error;
 });

and then you can do this in your controller:

app.controller('AppCtrl', function($scope, $http, agrService) {
     agrService.bannerSlides().then(function (data) {
         $scope.slides = data;
     });
})

Upvotes: 4

Ben Diamant
Ben Diamant

Reputation: 6206

You can't return a regular variable from an async call because by the time this success block is excuted the function already finished it's iteration. You need to return a promise object (as a guide line, and preffered do it from a service).

Following angular's doc for $q and $http you can build yourself a template for async calls handling.

The template should be something like that:

angular.module('mymodule').factory('MyAsyncService', function($q, http) {

var service = {
    getData: function() {
        var params ={};
        var deferObject = $q.defer();
        params.nameId = 1;
        $http.get('/data', params).success(function(data) {
            deferObject.resolve(data)
        }).error(function(error) {
            deferObject.reject(error)
        });

        return $q.promise;
    }
}
});

angular.module('mymodule').controller('MyGettingNameCtrl', ['$scope', 'MyAsyncService', function ($scope, MyAsyncService) {

    $scope.getData= function() {
        MyAsyncService.getData().then(function(data) {
            //do something with data
        }, function(error) {
            //Error 
        })
    }
}]);

Upvotes: 0

Tristan
Tristan

Reputation: 3232

You need to return a promise and update your scope in the callback:

app.service('agrService', function ($q, $http) {

 this.bannerSlides = function(){
    var ret = $q.defer();
    var dataUrl = "data/banner-rotator.json";

    // Simple GET request example :
    $http({
        method: 'GET',
        dataType: "json",
        url: dataUrl
    })
    .success( function(data, status, headers, config) {

        // this callback will be called asynchronously
        // when the response is available

        ret.resolve(data);

    }).error( function(data, status, headers, config) {

        // called asynchronously if an error occurs
        // or server returns response with an error status.
        ret.reject("Niente, Nada, Caput");
    });
    return ret.promise;

 }
})

app.controller('AppCtrl', function($scope, $http, agrService) {
 $scope.slides = null;

 agrService.bannerSlides().then(function(data){
   $scope.slides = data;
 }, function(error){
   // do something else
 });

})

Upvotes: 0

Related Questions