salep
salep

Reputation: 1390

Angularjs pass variable to factory from controller

I'm trying to create a basic pagination. Backend is ready and tested. Each page contains 10 activity.

/feed/1 -> displays 0-10
/feed/2 -> displays 10-20
/feed/3 -> displays 20-30

I want to start at 1 and increment page number by one (and load that page's data into page) when the button is clicked, but I can't see anything on the page when I view it. incr() also doesn't work, throws

TypeError: t.data.push is not a function

error. (I use Gulp)

What is the problem here?

Url routing (I use ui-router's resolve feature)

angular.module('site.feed.routes')

.run(
  ['$rootScope', '$state', '$stateParams',
    function($rootScope, $state, $stateParams) {
      $rootScope.$state = $state;
      $rootScope.$stateParams = $stateParams;
    }
  ]
)

.config(
  ['$stateProvider', '$urlRouterProvider', '$locationProvider',
    function($stateProvider, $urlRouterProvider, $locationProvider) {

      $locationProvider.html5Mode({
        enabled: true,
        requireBase: false
      });

      $stateProvider
        .state('posttest', {
          url: '/feed',
          templateUrl: 'feed.html',
          resolve: {
            data: 'PostData',
          },
          controller: 'PostController'
        });
    }
  ]
);

Factory

angular.module('site.feed').factory('PostData', ["$http", function($http) {

  return {
    getPage: function(pageNumber) {
      return $http.get('/feed/' + pageNumber).then(function(response) {
        return response.data;
      });
    }
  };
}]);

Controller

angular.module('site.feed').controller('PostController', ['$scope', 'data', 'PostData', function($scope, data, PostData) {
  $scope.page = 1;
  $scope.data = data; // first page

  $scope.incr = function() {
    $scope.page++;
    PostData.getPage($scope.page).then(function(returned) {
      $scope.data.push(returned.data);
    });

  };
}]);

feed.html

<div ng-repeat="feedflow in data">
  <div ng-repeat="ehe in feedflow.feed">
    {{feedflow.id}}
    {{ehe.status}}
  </div>
</div>

{{page}}
<button ng-click="incr()">Increment by one</button>

Upvotes: 0

Views: 1591

Answers (1)

Minato
Minato

Reputation: 4533

A quick fix would be to pass in you data to the factory and let it update the variable, since it'll be a reference it'll be good.

getPage: function(pageNumber, data) {
  return $http.get('/feed/' + pageNumber).then(function(response) {
    data.push(response.data);
  });
}

and when calling the factory

PostData.getPage($scope.page, $scope.data);

another fix is simple just remove the then part.

getPage: function(pageNumber) {
  return $http.get('/feed/' + pageNumber);
}

--- explaination

since you are calling multiple then on a promise.. first being inside the service

then(function(response) {
   return response.data;
});

second being.

PostData.getPage($scope.page).then(function(returned) {
   $scope.data.push(returned.data);
});

when you attach multiple then each one is called one after the other. the problem with your code is you are returning in the first then which prevents the 2nd to execute.. I found your first then useless so I asked you to remove it.. hence the 2nd fix.

First fix simply passes the $scope.data and since $scope.data will be a reference so the modifications will be reflected inside the variable.

Upvotes: 1

Related Questions