angular.module('demoApp', [])
.controller('MainController', MainController)
.directive('component1', Component1)
.directive('component2', Component2)
.directive('component3', Component3)
.factory('sharedData', SharedData)
.factory('sharedDataEvents', SharedDataEvents);
function MainController(sharedData) {
sharedData.setItems([{
id: 0,
test: 'hello 0'
}, {
id: 1,
test: 'hello 1'
}, {
id: 2,
test: 'hello 2'
}]);
this.items = sharedData.getItems();
this.selection = this.items[0];
}
function Component1() {
return {
restrict: 'E',
scope: {},
bindToController: {
selection: '='
},
template: 'Comp1 selection: {{comp1Ctrl.selection}}'+
'<ul><li ng-repeat="item in comp1Ctrl.items" ng-click="comp1Ctrl.select(item)">{{item}}</li></ul>',
controller: function($scope, sharedData, sharedDataEvents) {
this.items = sharedData.getItems();
this.select = function(item) {
//console.log(item);
this.selection = item
sharedData.setSelection(item);
};
sharedDataEvents.addListener('onSelect', function(selected) {
console.log('selection changed comp. 1 listener callback', selected);
});
},
controllerAs: 'comp1Ctrl'
};
}
function Component2() {
return {
restrict: 'E',
scope: {},
bindToController: {
selection: '@'
},
template: 'Comp2 selection: {{comp2Ctrl.selection}}',
controller: function(sharedDataEvents) {
sharedDataEvents.addListener('onSelect', function(selected) {
console.log('selection changed comp. 2 listener callback', selected);
});
},
controllerAs: 'comp2Ctrl'
};
}
function Component3() {
//only listening and alert on every third change
return {
restrict: 'E',
controller: function($window, sharedDataEvents) {
var count = 0;
sharedDataEvents.addListener('onSelect', function(selected, old) {
console.log('selection changed comp. 3 listener callback', selected, old);
if (++count === 3) {
count = 0;
$window.alert('changed selection 3 times!!! Detected by Component 3');
}
});
}
}
}
function SharedData(sharedDataEvents) {
return {
selection: {},
items: [],
setItems: function(items) {
this.items = items
},
setSelection: function(item) {
this.selection = item;
sharedDataEvents.onSelectionChange(item);
},
getItems: function() {
return this.items;
}
};
}
function SharedDataEvents() {
return {
changeListeners: {
onSelect: []
},
addListener: function(type, cb) {
this.changeListeners[type].push({ cb: cb });
},
onSelectionChange: function(selection) {
console.log(selection);
var changeEvents = this.changeListeners['onSelect'];
console.log(changeEvents);
if ( ! changeEvents.length ) return;
angular.forEach(changeEvents, function(cbObj) {
console.log(typeof cbObj.cb);
if (typeof cbObj.cb == 'function') {
// callback is a function
if ( selection !== cbObj.previous ) { // only trigger if changed
cbObj.cb.call(null, selection, cbObj.previous);
cbObj.previous = selection; // new to old for next run
}
}
});
}
};
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.7/angular.js"></script>
<div ng-app="demoApp" ng-controller="MainController as ctrl">
<p>Click on a list item to change selection:</p>
<component1 selection="ctrl.selection"></component1> <!-- can change the selection -->
<component2 selection="{{ctrl.selection}}"></component2>
<component3></component3>
</div>