Reputation: 869
I have a Factory:
function PeriodDataService (APIService) {
var periodData = {}
periodData.refresh = function(user) {
APIService.query({ route:'period', id: user._id }, function(data) {
periodData.orders = data[0].orders
})
}
periodData.orders = []
periodData.preiod = 1
return periodData
}
angular
.module('app')
.factory('PeriodDataService', PeriodDataService)
And some controllers...for example this one, which use the factory data
function ProductionCtrl ($scope, PeriodDataService) {
$scope.board = PeriodDataService.board
$scope.period = PeriodDataService.period
}
angular
.module('loop')
.controller('ProductionCtrl', ProductionCtrl)
When I call the refresh, the Controlles dont update there data. Whats the reason?
PeriodDataService.refresh(user)
Thank you!
Upvotes: 0
Views: 776
Reputation: 1945
I used $rootScope in the factory and $scope.$on in the controller to solve this. When I change the factory, i use $rootScope.$broadcast to tell the controller that I change it.
.factory('dataFactory', ['$http', '$rootScope', function ($http, $rootScope) {
var dataFactory = {
stock: null,
getStock: getStock
}
function getStock() {
$http.get("/api/itemfarmacia/").then(function success(res) {
dataFactory.stock = res.data;
$rootScope.$broadcast('dataFactory.stock');
}, function error(err) {
onsole.log("Bad request");
})
}
return dataFactory;
}])
and in the controller
.controller('atencion', ["$scope", "$state", "dataFactory", function ($scope, $state, dataFactory) {
$scope.stock = dataFactory.stock;
dataFactory.getStock(); //wherever you execute this, $scope.stock will change
$scope.$on('dataFactory.stock', function () {
$scope.stock = dataFactory.stock; //Updating $scope
})
}])
Upvotes: 0
Reputation: 2324
The problem is that, when you call refresh
and your service does
periodData.orders = data[0].orders
your service is changing the periodData.orders
property to point to a different array than the one it was set to point to when you initialized it (via periodData.orders = []
).
This breaks the connection between your controller and the data array in your service because your controller was set up to point to the original array when you did
$scope.orders = PeriodDataService.orders
(which I don't actually see in your sample code but which I assume you're doing somewhere).
This simply set $scope.orders
equal to the same pointer as periodData.orders
, thus pointing to the original array in memory, and allowing the controller to see changes to that array.
When your service changes periodData.orders
to a different pointer, nothing changes the pointer value of $scope.orders
, so it's still pointing to the original array, which hasn't changed.
There are different ways you can fix this.
You could have your service .push()
the new data into periodData.orders
rather than set periodData.orders
equal to the returned data array. So your refresh
method would look like this:
periodData.refresh = function(user) {
APIService.query({ route:'period', id: user._id }, function(data) {
periodData.orders.length = 0; // empty current orders array
// push the returned orders data into orders array
data[0].orders.forEach(function (item, index) {
periodData.orders.push(item);
});
});
};
As long as you just add to or remove from the original array, and don't redefine it (don't ever do another periodData.orders =
), it should work fine.
Alternatively, you could create a new object to hold the orders
array (and any other data elements you want to expose) and have a $scope
property pointing to that object rather than to the array itself.
So your service would look like this:
function PeriodDataService (APIService) {
var periodDataSvc = {};
// create data object to hold service data
periodDataSvc.periodData = {
orders: [],
period: 1
};
periodDataSvc.refresh = function(user) {
APIService.query({ route:'period', id: user._id }, function(data) {
periodDataSvc.periodData.orders = data[0].orders
})
}
return periodDataSvc;
}
with the orders
array now one level deeper at periodDataSvc.periodData.orders
.
And you would have a $scope
property pointing to the periodData
object rather than to the orders
array:
function ProductionCtrl($scope, PeriodDataService) {
$scope.periodData = PeriodDataService.periodData;
}
So in your service, when you set the orders
array equal to the returned array from your APIService, the controller will see that change because it's watching the periodData
object, and a property on that object has changed.
And of course, since you changed the $scope
property, any markup that was referencing the orders
array would also then need to change to reference periodData.orders
instead. For example:
<div ng-repeat="order in periodData.orders">{{order.id}}: {{order.item}}</div>
Here's a fiddle showing both approaches.
Upvotes: 1