Reputation: 12887
So let's say I have a controler that dppends on a news
service. Whenever news is published, the controller would like to diisplay the latest news. I'd rather not use $broadcast
and $on
, because this does weird things to the way components are coupled. Components which don't depend on news
could still listen for these events.
So, here's what I'd like to be able to do:
myApp.controller("myController", ["news", function(news){
news.onPublish.addListener(function(story){
... Show the latest juicy story.
});
}]);
news.onPublish
would be an Event instance, with Event
defined as follows:
Event = function(){
var listeners = [];
this.addListener = function(l){
listeners.push(l);
}
this.trigger = function(){
var params = arguments
listeners.map(function(l){
l.apply(undefined, params);
});
}
return this
}
Is this a good way to implement communication between services and other components? Also, would it be good to call $rootScope.$apply
at the end of Event.trigger
so that any changes the listeners made will be picked up?
Upvotes: 1
Views: 126
Reputation: 2996
The best is to write common data storing factories that do the job for you. Here's a working example: http://jsfiddle.net/9L5xL8sx/ which shows how this works. The NewsService
factory can be used across several Angular modules, and within the same module, as shown in my example.
Here's the JS:
var app = angular.module("TestSharing", []);
app.factory("NewsService", [function() {
var articles = [];
var makeNews = function (text) {
articles.push({text: text});
};
var getNews = function() {
return articles;
};
return {
get: getNews,
make: makeNews
};
}]);
app.controller("FirstCtrl", ["$scope", "NewsService", function($scope, NewsService) {
$scope.articles = function () {
return NewsService.get();
};
}]);
app.controller("SecondCtrl", ["$scope", "NewsService", function($scope, NewsService) {
$scope.articletext = "";
$scope.submit = function () {
NewsService.make($scope.articletext);
};
}])
The HTML:
<div ng-app="TestSharing">
<div ng-controller="FirstCtrl">
<span ng-repeat="article in articles()">{{article.text}}<br/></span>
</div>
<div ng-controller="SecondCtrl">
<input type="text" ng-model="articletext"/>
<button ng-click="submit()">Make some news</button>
</div>
</div>
Also, services like these can also share events. For example, if you'd used the factory to expose an object called somethingNew
, which merely contained if something new had happened in one of the Controllers it had been shared in, you could achieve the same effect. The idea would be to only listen for changes where you'd want (using something like $scope.$watch(NewsService.somethingNew, function (now, then) {…})
) and that would be just as easy.
Upvotes: 1