I'm trying to sent an array filled with objects from controller 1 to controller 2. But all I get in controller 2 is an empty array. The only way I get a filled one is when I create a static array in my service.
My service
app.service('myData', function () {
this.myData = [];
this.addData = function(data) {
this.myData.push(data);
}
this.getData = function() {
return this.myData;
}});
controller 1 which sets the data
app.controller('controller1',['$scope', 'myData', function($scope, myData) {
$scope.addData = function(index, name) {
myData.addData({index: index, name: name});
}}]);
Controller 2 looks like this
app.controller('controller2',['$scope', 'myData', function($scope, myData) {
$scope.myData = myData.getData();
$scope.$watch('myData.getData()', function(data){
console.log(data);
});
console.log($scope.myData);}]);
When I was searching for an answer I found alot of questions almost similar to mine. The only difference was that I fill my service from my controller instead of creating a static service.
Both my console.logs return an empty array. Why is this?
4 Answers 4
Your $watch expression should be a function (see the docs for $watch). Giving $watch a string tells Angular to inspect a property on the $scope. As well as this, you have mistakenly referenced your myData service as 'data' in the string 'data.getData()'.
1) Watch the result of myData#getData:
$scope.$watch(function () {
return myData.getData();
}, function (data) {
console.log(data);
});
2) Watch the reference to the myData service's internal array on $scope:
$scope.myData = myData.getData();
$scope.$watch('myData', function (data) {
console.log(data);
});
Comments
It should work if you call the addData from the first controller for example:
.controller('tourCtrl', ['$scope', 'myData', function ($scope, myData) {
$scope.addData = function (index, name) {
myData.addData({
index: index,
name: name
});
}
$scope.addData('hello', 'world');
}])
.controller('controller2', ['$scope', 'myData', function ($scope, myData) {
$scope.myData = myData.getData();
$scope.$watch('myData', function (data) {
console.log(data);
});
console.log($scope.myData);
}]);
Comments
i would suggest that you use something like pubsub mechanism. you can't know when will data appear. and watching a function is an expensive operation. You can build a PubSub mechanism on your service.
A controller could register for an event and another could publish that event. so with minimum resources you could achieve what you want.
here is a sample
app.factory('pubSubService', [function() {
var pubSubAPI = {};
var hooks = [];
pubSubAPI.publishEvent = function(message) {
for (var i = 0; i < hooks.length; i++) {
hooks[i](message);
}
};
pubSubAPI.subscribeEvent = function(eventFunction) {
hooks.push(eventFunction);
};
return pubSubAPI;
}]);
2 Comments
Another Approach would be to use the Observer Pattern, saves having to use the $watchat all:
app.service('myData', function () {
this.myData = [];
var observers = [];
var self = this;
this.addObserver = function (callback) {
observers.push(callback);
};
var notifyObservers = function () {
angular.forEach(observers, function (callback) {
callback(self.myData);
});
};
this.addData = function (data) {
this.myData.push(data);
notifyObservers();
}
});
app.controller('controller2', ['$scope', 'myData', function ($scope, myData) {
myData.registerObserverCallback(function (data) {
$scope.myData = data;
console.log(data);
});
}]);
function(){ return myData.getData() }instead ofdata.getData()