Skip to content Skip to sidebar Skip to footer

Data Not Defined In Link Function After $http Request In Angular

I have the following code. controller.js angular.module('LiveAPP.main',['LiveAPP.factory']) .controller('mainCtrl', ['$scope','$http', '$location','dataFactory',mainCtrl]) .direct

Solution 1:

If you're using angular ui-router you could also use resolve. With resolve you can do the $http before the controller starts.

You can use resolve to provide your controller with content or data that is custom to the state. resolve is an optional map of dependencies which should be injected into the controller.

If any of these dependencies are promises, they will be resolved and converted to a value before the controller is instantiated and the $stateChangeSuccess event is fired.

from the docs.

Please have a look at the demo below or this jsfiddle.

angular.module('demoApp', ['ui.router'])
    .config(function ($urlRouterProvider, $stateProvider) {
    $urlRouterProvider.otherwise('/');
    $stateProvider.state('home', {
        url: '/',
        template: '<ratehome></ratehome><ratehome></ratehome><ratehome></ratehome>',
        controller: 'mainCtrl',
        resolve: {
            artists: function (artistsService) {
                console.log('Resolve');
                return artistsService.get(); //'/artistsearch',//artistsService.get();
            }
        }
    });
})
    .controller('mainCtrl', ['$scope', '$http', '$location', 'artists', MainCtrl])

    .directive('ratehome', function () {
    return {
        restrict: "E",
        template: '<div id="rateYo"><ul><li ng-repeat="artist in recentArtist">{{artist}}</li></ul></div>',
        link: function (scope, elem, attrs) {
            console.log("NEW", scope.recentArtist);
        }
    }
})

    .factory('artistsService', function ($http) {
    return {
        get: function () {
            console.log('getting');
            return $http({
                method: 'GET',
                url: 'http://crossorigin.me/http://www.mocky.io/v2/558b30615f3dcbc414067170', //'/artistsearch',//params: {getArtist: "all"}
            }).then(function (recent) {
                //console.log(recent);return recent.data;
            });
        }
    };
});

functionMainCtrl($scope, $http, $location, artists) {

    $scope.recentArtist = artists;
    console.log('ctrl', artists);    

}
<scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.1/angular.js"></script><scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.15/angular-ui-router.js"></script><divng-app="demoApp"><divui-view=""></div></div>

Solution 2:

AS your directive is not using isolated scope, that does mean you can directly access your controller scope inside your directive. I'd suggest you to to put that $watch inside directive link instead of your controller. That would intimate you that the ajax has been completed and data got changed & you get those changed value inside watcher function.

Code

.directive('ratehome',function(){
  return {
    restrict:"E",
    template: "<div id='rateYo'></div>",
    link: function(scope, ele, attrs){
      $scope.$watch('recentArtist',function(newValue,oldValue){
        console.log("NEW",newValue)
      });
    }
  }
})

Solution 3:

Your link function is running before the $http response comes back as you suspect. You can wait for it by using $broadcast and $on:

angular.module('LiveAPP.main',['LiveAPP.factory'])
    .controller('mainCtrl', ['$scope','$http', '$location','$rootScope','dataFactory',mainCtrl])
    .directive('ratehome',function(){
        return {
            restrict:"E",
            template: "<div id='rateYo'></div>",
            link: function(scope, ele, attrs){
                scope.$on('artistLoaded', function(){
                    console.log("NEW",scope.recentArtist);
                });
            }
        };
    });


functionmainCtrl($scope,$http,$location,$rootScope,dataFactory){
    $scope.getRecentArtists = function(){
        return$http({
            method: 'GET',
            url: '/artistsearch',
            params: {getArtist: "all"}
        }).then(function(recent){
            $scope.recentArtist = recent.data
            $rootScope.$broadcast('artistLoaded');
        });
    };

    $scope.getRecentArtists();
    $scope.recentArtist = "";

    $scope.$watch('recentArtist',function(newValue,oldValue){
        $scope.recentArtist = newValue
    });
}  

This way the code will not run until the response has been returned and set

Post a Comment for "Data Not Defined In Link Function After $http Request In Angular"