[フレーム]
Last Updated: July 15, 2016
·
4.161K
· sirtophamhatt

AngularJS Mediator Pattern

Synopsis

A standard Mediator Pattern applied to AngularJS which does not use $broadcasts or $emits.

  • Avoids unnecessary injecting and exposing of $scope onto one's view where controllerAs is preferred.
  • Circumvents using $rootScope to update viewmodels existing on sibling $scope paths.
  • Does not trigger additional $apply or $digest cycles.
  • Employs lodash for better cross-browser performance.
  • Mediator.subscribe returns a function to deregister the subscriber, similar to Angular's $scope.$on implementation.

( function( angular , _ ) {
 function MediatorService( $log ) {
 var Mediator = {};

 var channels = {};
 var subscriberId = 0;


 Mediator.publish = function( channel , publisher , data ) {
 if ( ! hasSubscriber( channel ) ) { 
 return;
 }

 var subscribers = channels[ channel ];

 _.map( subscribers, function( subscriber ) {
 try {
 subscriber.callback( data );
 } catch ( e ) {
 $log.error( e , publisher , subscriber.name )
 }
 } );
 };


 Mediator.subscribe = function( channel , subscriber , callback ) {
 if ( ! hasSubscriber( channel ) ) {
 channels[ channel ] = [ ];
 }

 channels[ channel ].push( {
 "callback" : callback ,
 "name" : subscriber ,
 "subscriberId" : ++subscriberId
 } );

 return function( ) {
 unsubscribe( subscriberId );
 };
 };


 function hasSubscriber( channel ) {
 return _.has( channels , channel );
 }


 function unsubscribe( subscriberId ) {
 channels = _.map( channels , function( channel ) {
 return _.filter( channel , function( subscriber ) {
 return subscriber.subscriberId !== subscriberId;
 });
 });
 }

 return Mediator;
 }

 angular
 .module( "app" )
 .factory( "Mediator" , [ "$log" , MediatorService ] );

} ) ( angular, _ );

Implementation

Plnkr

HTML

<div data-first=""></div>
<div data-second=""></div>

JS

angular
 .module( "app" , [ ] )
 .factory( "Mediator" , [ "$log", MediatorService ] )
 .directive( "first" , function( ) { 
 return {
 controller: function( ) {
 this.name = "First"; 
 },
 controllerAs: "first",
 template: "<p ng-bind='first.name'></p><div data-third></div>"
 }; 
 } )
 .directive( "second" , function( Mediator ) { 
 return {
 controller: function( ) {
 this.name = "Second"; 
 this.publishNewName = Mediator.publish.bind( this , "NewName" , "second" , this.name );
 },
 controllerAs: "second",
 template: "<a ng-bind='second.name' ng-click='this.publishNewName( )'></a>"
 }; 
 } )
 .directive( "third" , function( Mediator ) {
 return {
 controller: function( ) {
 this.name = "Third";
 var unsubscribe = Mediator.subscribe( "NewName" , "third" , setName.bind( this ) ); 

 function setName(name) {
 this.name = name;
 unsubscribe( );
 }
 },
 controllerAs: "third",
 template: "<p ng-bind='third.name'></p>"
 }; 
 } );

1 Response
Add your response

Why did you reinvent $broadcast/$emit and $on? What's better about this method than using events?

over 1 year ago ·

AltStyle によって変換されたページ (->オリジナル) /