|
36 | 36 | * [Others](#others)
|
37 | 37 | * [Module Pattern](#module-pattern)
|
38 | 38 | * [Data Mapper](#data-mapper)
|
| 39 | + * [Observer Pattern as an External Service](#observer-pattern-as-an-external-service) |
39 | 40 | * [References](#references)
|
40 | 41 |
|
41 | 42 | <!--endtoc-->
|
@@ -794,94 +795,38 @@ will produce the same result as the one above. The main difference here is that
|
794 | 795 |
|
795 | 796 | 
|
796 | 797 |
|
797 |
| -##### About |
798 |
| -Below is an example taken from https://github.com/greglbd/angular-observer-pattern. This is an angular factory which reflects the Observer Pattern it works well with the ControllerAs method of working as it can be much more efficient that $scope.$watch and more specific to a unique scope or object than $emit and $broadcast when used correctly. |
799 |
| - |
800 |
| -**Use Case:** You would use this pattern to communicate between 2 controllers that use the same model but are not connected in anyway |
801 |
| - |
802 |
| -##### Methods |
803 |
| - |
804 |
| -function adds a listener to an event with a callback which is stored against the event with it's corresponding id. |
805 |
| -``` |
806 |
| -_observerService.attach = function(callback, event, id) |
807 |
| -``` |
808 |
| - |
809 |
| - |
810 |
| -function removes all occurences of one id from all events in the observer object |
811 |
| -``` |
812 |
| -_observerService.detachById = function(id) |
813 |
| -``` |
814 |
| - |
815 |
| - |
816 |
| -function removes all occurences of the event from the observer Object |
817 |
| -``` |
818 |
| -_observerService.detachByEvent = function(event) |
819 |
| -``` |
| 798 | +There are two basic ways of communication between the scopes in an AngularJS application. The first one is calling methods of parent scope by a child scope. This is possible since the child scope inherits prototypically by its parent, as mentioned above (see [Scope](#scope)). This allows communication in a single direction - child to parent. Some times it is necessary to call method of given child scope or notify it about a triggered event in the context of the parent scope. AngularJS provides built-in observer pattern, which allows this. Another possible use case, of the observer pattern, is when multiple scopes are interested in given event but the scope, in which context the event is triggered, is not aware of them. This allows decoupling between the different scopes, non of the scopes should be aware of the rest of the scopes. |
820 | 799 |
|
| 800 | +Each AngularJS scope has public methods called `$on`, `$emit` and `$broadcast`. The method `$on` accepts topic as first argument and callback as second. We can think of the callback as an observer - an object, which implements the `Observer` interface (in JavaScript the functions are first-class, so we can provide only implementation of the `notify` method): |
821 | 801 |
|
822 |
| -removes all callbacks for an id in a specific event from the observer object |
823 |
| -``` |
824 |
| -_observerService.detachByEventAndId = function(event, id) |
| 802 | +```JavaScript |
| 803 | +function ExampleCtrl($scope) { |
| 804 | + $scope.$on('event-name', function handler() { |
| 805 | + //body |
| 806 | + }); |
| 807 | +} |
825 | 808 | ```
|
826 | 809 |
|
| 810 | +In this way the current scope "subscribes" to events of type `event-name`. When `event-name` is triggered in any parent or child scope of the given one, `handler` would be called. |
827 | 811 |
|
828 |
| -Notifies all observers of a specific event, can pass a params variable of any type |
829 |
| -``` |
830 |
| -_observerService.notify = function(event, parameters) |
831 |
| -``` |
832 |
| - |
| 812 | +The methods `$emit` and `$broadcast` are used for triggering events respectively upwards and downwards through the scope chain. |
| 813 | +For example: |
833 | 814 |
|
834 |
| -##### Controller Example |
835 |
| -Below example shows how to attach, notify and detach an event. |
836 |
| -``` |
837 |
| -angular.module('app.controllers') |
838 |
| - .controller('ObserverExample',ObserverExample); |
839 |
| -ObserverExample.$inject= ['ObserverService','$timeout']; |
840 |
| -function ObserverExample(ObserverService, $timeout) { |
841 |
| - var vm = this; |
842 |
| - var id = 'vm1'; |
843 |
| - ObserverService.attach(callbackFunction, 'let_me_know', id) |
844 |
| - |
845 |
| - function callbackFunction(params){ |
846 |
| - console.log('now i know'); |
847 |
| - ObserverService.detachByEvent('let_me_know') |
848 |
| - } |
849 |
| - |
850 |
| - $timeout(function(){ |
851 |
| - ObserverService.notify('let_me_know'); |
852 |
| - },5000); |
| 815 | +```JavaScript |
| 816 | +function ExampleCtrl($scope) { |
| 817 | + $scope.$emit('event-name', { foo: 'bar' }); |
853 | 818 | }
|
854 | 819 | ```
|
855 |
| -Alternative way to remove event |
856 | 820 |
|
857 |
| -``` |
858 |
| -angular.module('app.controllers') |
859 |
| - .controller('ObserverExample',ObserverExample); |
860 |
| -ObserverExample.$inject= ['ObserverService','$timeout', '$scope']; |
861 |
| -function ObserverExample(ObserverService, $timeout, $scope) { |
862 |
| - var vm = this; |
863 |
| - var id = 'vm1'; |
864 |
| - ObserverService.attach(callbackFunction, 'let_me_know', id) |
865 |
| - |
866 |
| - function callbackFunction(params){ |
867 |
| - console.log('now i know'); |
868 |
| - } |
869 |
| - |
870 |
| - $timeout(function(){ |
871 |
| - ObserverService.notify('let_me_know'); |
872 |
| - },5000); |
873 |
| - |
874 |
| - // Cleanup listeners when this controller is destroyed |
875 |
| - $scope.$on('$destroy', function handler() { |
876 |
| - ObserverService.detachByEvent('let_me_know') |
877 |
| - }); |
878 |
| -} |
879 |
| -``` |
880 |
| -**Public Repository to get you started** |
881 |
| -https://github.com/greglbd/angular-observer-pattern |
| 821 | +The scope in the example above, triggers the event `event-name` to all scopes upwards. This means that each of the parent scopes of the given one, which are subscribed to the event `event-name`, would be notified and their handler callback will be invoked. |
| 822 | + |
| 823 | +Analogical is the case when the method `$broadcast` is called. The only difference is that the event would be transmitted downwards - to all children scopes. |
| 824 | +Each scope can subscribe to any event with multiple callbacks (i.e. it can associate multiple observers to given event). |
882 | 825 |
|
883 | 826 | In the JavaScript community this pattern is better known as publish/subscribe.
|
884 | 827 |
|
| 828 | +For a best practice example see [Observer Pattern as an External Service](#observer-pattern-as-an-external-service) |
| 829 | + |
885 | 830 | #### Chain of Responsibilities
|
886 | 831 |
|
887 | 832 | >The chain-of-responsibility pattern is a design pattern consisting of a source of command objects and a series of processing objects. Each processing object contains logic that defines the types of command objects that it can handle; the rest are passed to the next processing object in the chain. A mechanism also exists for adding new processing objects to the end of this chain.
|
@@ -1146,6 +1091,94 @@ And the following partial:
|
1146 | 1091 | </div>
|
1147 | 1092 | ```
|
1148 | 1093 |
|
| 1094 | +### Observer Pattern as an External Service |
| 1095 | +
|
| 1096 | +##### About |
| 1097 | +Below is an example taken from https://github.com/greglbd/angular-observer-pattern. This is an angular factory which reflects the Observer Pattern. It works well with the ControllerAs method of working as it can be much more efficient that $scope.$watch and more specific to a unique scope or object than $emit and $broadcast when used correctly. |
| 1098 | +
|
| 1099 | +**Use Case:** You would use this pattern to communicate between 2 controllers that use the same model but are not connected in anyway |
| 1100 | +
|
| 1101 | +##### Methods |
| 1102 | +
|
| 1103 | +function adds a listener to an event with a callback which is stored against the event with it's corresponding id. |
| 1104 | +``` |
| 1105 | +_observerService.attach = function(callback, event, id) |
| 1106 | +``` |
| 1107 | + |
| 1108 | + |
| 1109 | +function removes all occurences of one id from all events in the observer object |
| 1110 | +``` |
| 1111 | +_observerService.detachById = function(id) |
| 1112 | +``` |
| 1113 | + |
| 1114 | + |
| 1115 | +function removes all occurences of the event from the observer Object |
| 1116 | +``` |
| 1117 | +_observerService.detachByEvent = function(event) |
| 1118 | +``` |
| 1119 | + |
| 1120 | + |
| 1121 | +removes all callbacks for an id in a specific event from the observer object |
| 1122 | +``` |
| 1123 | +_observerService.detachByEventAndId = function(event, id) |
| 1124 | +``` |
| 1125 | + |
| 1126 | + |
| 1127 | +Notifies all observers of a specific event, can pass a params variable of any type |
| 1128 | +``` |
| 1129 | +_observerService.notify = function(event, parameters) |
| 1130 | +``` |
| 1131 | + |
| 1132 | + |
| 1133 | +##### Controller Example |
| 1134 | +Below example shows how to attach, notify and detach an event. |
| 1135 | +```javascript |
| 1136 | +angular.module('app.controllers') |
| 1137 | + .controller('ObserverExample',ObserverExample); |
| 1138 | +ObserverExample.$inject= ['ObserverService','$timeout']; |
| 1139 | +function ObserverExample(ObserverService, $timeout) { |
| 1140 | + var vm = this; |
| 1141 | + var id = 'vm1'; |
| 1142 | + ObserverService.attach(callbackFunction, 'let_me_know', id) |
| 1143 | + |
| 1144 | + function callbackFunction(params){ |
| 1145 | + console.log('now i know'); |
| 1146 | + ObserverService.detachByEvent('let_me_know') |
| 1147 | + } |
| 1148 | + |
| 1149 | + $timeout(function(){ |
| 1150 | + ObserverService.notify('let_me_know'); |
| 1151 | + },5000); |
| 1152 | +} |
| 1153 | +``` |
| 1154 | +Alternative way to remove event |
| 1155 | +
|
| 1156 | +```javascript |
| 1157 | +angular.module('app.controllers') |
| 1158 | + .controller('ObserverExample',ObserverExample); |
| 1159 | +ObserverExample.$inject= ['ObserverService','$timeout', '$scope']; |
| 1160 | +function ObserverExample(ObserverService, $timeout, $scope) { |
| 1161 | + var vm = this; |
| 1162 | + var id = 'vm1'; |
| 1163 | + ObserverService.attach(callbackFunction, 'let_me_know', id) |
| 1164 | + |
| 1165 | + function callbackFunction(params){ |
| 1166 | + console.log('now i know'); |
| 1167 | + } |
| 1168 | + |
| 1169 | + $timeout(function(){ |
| 1170 | + ObserverService.notify('let_me_know'); |
| 1171 | + },5000); |
| 1172 | + |
| 1173 | + // Cleanup listeners when this controller is destroyed |
| 1174 | + $scope.$on('$destroy', function handler() { |
| 1175 | + ObserverService.detachByEvent('let_me_know') |
| 1176 | + }); |
| 1177 | +} |
| 1178 | +``` |
| 1179 | +**Public Repository to get you started** |
| 1180 | +https://github.com/greglbd/angular-observer-pattern |
| 1181 | +
|
1149 | 1182 | ## References
|
1150 | 1183 |
|
1151 | 1184 | 1. [Wikipedia](https://en.wikipedia.org/wiki). The source of all brief descriptions of the design patterns is wikipedia.
|
|
0 commit comments