I'm trying angularjs for the first time and created a service that I use to make ajax calls to my application API and retrieve a paginated list. I called it "GridService". The service is injected into a controller and everything works great! Until I tried to use the same service twice inside two different controllers on the same page. To my horror, the second instance of the service overwrites the first (doh)
For example; I render two partials as follows :
<div id="location_areas" class="container tab-pane fade" ng-controller="areasController" ng-init="initialise()">
@include('areas._areas')
</div>
<div id="location_people" class="container tab-pane fade" ng-controller="peopleController" ng-init="initialise()">
@include('people._people')
</div>
and I inject the service into a controller as follows and link to the service properties
angular.module('areasController', [])
.controller('areasController', function($scope, $attrs, $http, AreaService, GridService, HelperService) {
$scope.areas = function() { return GridService.getListing() }
$scope.totalPages = function() { return GridService.getTotalPages() }
$scope.currentPage = function() { return GridService.getCurrentPage() }
$scope.columns = function() { return GridService.getColumns() }
Lastly, my abbreviated service is as simple as
angular.module('gridService', [])
.provider('GridService', function($http) {
var columns = {};
var filters = {};
var listing = [];
var totalPages = 0;
var range;
var currentPage = 1;
return {
/**
* Get the requested data (JSON format) from storage then populate the class properties which
* are bound to equivalent properties in the controller.
*
* @return void
*/
list : function(url,pageNumber,data) {
url = url+'?page='+pageNumber;
for (var key in data) {
if( angular.isArray( data[key] ) )
{
angular.forEach( data[key], function( value ) {
url = url+'&'+key+'[]='+value;
});
}
else
{
url = url+'&'+key+'='+data[key];
}
}
$http({ method: 'GET', url: url })
.then(function(response) {
listing = response.data.data;
totalPages = response.data.last_page;
range = response.data.last_page;
currentPage = response.data.current_page;
// Pagination Range
var pages = [];
for(var i=1;i<=response.data.last_page;i++) {
pages.push(i);
}
range = pages;
});
},
Obviously I have boobed (doh). Is it possible to create this scenario or have I misunderstood angularjs architecture?
Please update your question with the relevant code for your service. Services in Angular are by definition Singletons. They should not have any private state. If they do have state, it should be state that is means to be shared between two controllers.
If you are just making $http requests in your service, it should just return the promise to the calling controllers -- not causing any "overlap".
UPDATE
It looks like you a missing a few lines from your service. It looks like it contains columns, filters, etc.
So this is the problem, it is a singleton. What you should do it break it up into two different classes, the network layer that still makes the AJAX call to get the data -- and a factory that returns a new instance of your Grid configuration.
So now the factory will return a new instance of the 'Grid' object for every time you call the factory. You need to call the factory like
gridFactory(url, pageNumber, data);