0

I have a page with a form in a modal. When the form in the modal is ready, I need to close the modal and display a message on the page. I would like the page and the modal to be separate controllers because they have different responsibilities. There are two methods I have found to notify the page that the form is ready:

  1. Create a service which both controllers get injected and call methods on that
  2. Make the modal controller a child of the page controller and let them share an object, like here: http://fdietz.github.io/recipes-with-angular-js/controllers/sharing-models-between-nested-controllers.html

The Angular documentation on scopes seem to say that controllers should not share variables but use services, but is that really the best way to go in this case?

Maarten
  • 4,643
  • 7
  • 37
  • 51
  • 1
    Since this seems to be more of eventing paradigm, look at scope methods `emit` and `broadcast`. They can be used to setup a simple pub\sub implementation that can be used for communication. – Chandermani Sep 12 '13 at 07:02
  • a third option which I forgot to mention indeed. You are right that this is an event, and so broadcast might be the best one. The only downside I see is that broadcasting is a bit 'heavy', goes through the whole app. Emit seems to be the fit: http://stackoverflow.com/a/14502755/105659 – Maarten Sep 12 '13 at 07:56
  • Depending upon who needs to send message to whom. Broadcast is top down, emit is bottom up. Also broadcast and emit do not go through the whole app. – Chandermani Sep 12 '13 at 08:30
  • this is bottom up, the modal needs to tell the parent that it has finished (success or error) – Maarten Sep 12 '13 at 09:34

1 Answers1

0

Use services to share information about controllers, but instead of injecting the controllers to your service, inject the service to the controllers. Also, if you want to remain the binding between your view and your data, you need to use objects instead of primitive variables.

angular.module("MyApp", [])
.factory("Data", function() {
  return { msg: "Shareable/Bindable data" }
})
.controller("One", function($scope, Data){
  $scope.foo = Data;
})
.controller("Two", function($scope, Data){
  $scope.bar = Data;
})

In this example, I could had just returned the data directly, instead of wrapping it in an object on my service. However, if we had done that (return "..." and $scope.foo = Data) , the variables {{foo}} or {{bar}} would only have a "shadow" copy of the factory information. Thus, we need to use {{foo.msg}} in our view and the message wrapping.

The full example is here in Codepen.io. Remove the { msg } and return the string instead to see what I mean.

jjperezaguinaga
  • 2,472
  • 14
  • 20