Allenph Allenph - 3 months ago 16
AngularJS Question

Multiple controllers manipulating content in an Angular directive?

I have a problem I haven't come across before, and I'm completely lost as to how to solve it.

I have a container which is used to display success and error messages across a wide variety of views. This container is defined by an Angular directive.

The problem is that I would like to have a service or something similar which I can inject into my controllers. I could then use methods on this service to make the "alert box" appear and/or change in content.

How do I go about achieving this or a similarly DRY setup in Angular?

Answer

Three perfectly good methods:

  1. Use angular's event system, rootScope.$broadcast or scope.$emit and scope.$on as listener, see the documentation here: https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$broadcast https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$emit https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$on

  2. inject the service into the "alert box" directive, let it register itself somehow with the service, that way the service knows of its existence and can control the directive's controller, or its scope, or the element directly, or whatever logic you wish to use.

  3. Use a container as parent, that has the orchestrating logic. the child directive's can require the container controller, and call functions etc. on the container, one child directive is then able to trigger another child through this orchestrating parent container.

EDIT: My point wasn't to show you how to do it in the most generic and cleanest way, because I don't know your exact situation, you should always consider how generic and abstracted you want your functionality. Here is a very very simple example to showcase that it's not about finding some complex system or pattern, but finding something that works well for you

method 2 example:

angular.module('myApp').service( 'myService', myService );

function myService(){
  this.alertBoxes = {};

  this.registerAlertBox = function(name, handle){
    this.alertBoxes[ name ] = handle;
  }

  this.toggleAlertBox = function(byName){
    this.alertBoxes[ byName ]();
  }
}

I personally would use method3 from the looks of what kind of functionality you're looking for, method 2 could be a generic pubsub service using rootScope.$broadcast and scope.$on, or not even bothering with those and doing it like a very straight forward pubsub.

method 1 really is the simplest way, but obviously would benefit from being abstracted away into a service, where you inject the service everytime you need a very specific pubsub event.

For an example of a pub/sub pattern: Pub/Sub design pattern angularjs service

Comments