Share data from child to parent controller

34,805 views
Skip to first unread message

Alexander Wilms

unread,
May 15, 2012, 3:20:04 PM5/15/12
to ang...@googlegroups.com
All, I am working on a dashboard that includes several "modules" with different contents, e.g. users tasklist, users calendar etc. The dashboard itself has a navigation menu and some additional features. Each module is implemented as it's own controller and template, so they can be re-used in other pages of the same application. So the app structure is like:
<MainController with navigation menu and app header>
 <TasklistController/> <CalendarController/> <OtherControllers/>
</MainController>
Now I'd like to some data from the "child modules" to be displayed in the parent controller, e.g. show the number of tasks in the app header. While I found some posts describing how to inherit data from the parent to the child controllers I'd like to have it the other way round. How can that be achieved?  (I am both a newbie to Angular and a designer, not a developers, so please keep it simple :-)
Thanks so much,
Alex

Peter Bacon Darwin

unread,
May 15, 2012, 3:27:31 PM5/15/12
to ang...@googlegroups.com
Try putting a field in the parent scope and then updating that directly in the child scopes.


--
You received this message because you are subscribed to the Google Groups "AngularJS" group.
To view this discussion on the web visit https://groups.google.com/d/msg/angular/-/PpWzqLkzp98J.
To post to this group, send email to ang...@googlegroups.com.
To unsubscribe from this group, send email to angular+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/angular?hl=en.

Alexander Wilms

unread,
May 16, 2012, 12:56:06 AM5/16/12
to ang...@googlegroups.com
Sorry, but that does not seem to work.

Vojta Jína

unread,
May 23, 2012, 11:39:07 PM5/23/12
to ang...@googlegroups.com
You can't access child scopes from parents.
There are reasons for that (eg. easier memory management - we can
easily throw away a child scope, without leaking memory).

Just do what Peter suggested. Define the property on parent scope and
access it from child scopes. Scopes inherit prototypically.
See this: http://jsfiddle.net/yjVD9/1/

V.

Ali Mills

unread,
May 23, 2012, 11:48:33 PM5/23/12
to ang...@googlegroups.com
Or... $emit (http://docs.angularjs.org/api/angular.module.ng.$rootScope.Scope#$emit)
an event from your child with the data as an argument that you want to
pass. Then, listen for the event on your parent.

Ali

vcaus...@gmail.com

unread,
Feb 19, 2014, 11:09:51 AM2/19/14
to ang...@googlegroups.com
I'm creating a directive that needs to interact with children directives generated through a template.

 <div my-parent="config" />

config is an object that defines:
  • the parent model
  • his controller (eg. AnnoyngParent_Ctrl) that extends BaseParent_Ctrl (and optionally a set of decorators)
  • a template e.g.   
    <h1>parent.title</h1>  
    <ng-repeat="child in parent.children" my-child="child" />

  • a list of children. Each child has a controller (eg. LazyChild_Ctrl), a model and a template
In both directives link functions I do add the controller and I compile the template.

It's quite easy to have children communicate with their parent (scope inheritance and $emit in the child controller, require "^myParent" + controller in the link phase of the directive).
Having the parent interact with their children is not as easy. $broadcast is an option for generic commands, not for more complex flows where at some point the parent needs to interact with a single child and do some conditional operation.
The second option we evaluated was using a shared service (or a combination of service and broadcast) but this makes the flow control cumbersome.

The last one we come through is to have the children "register" to the parent controller ( $scope.registerAsChild(this); ). While this seams a bad approach I've seen that something similar is used in the ngSwitch-ngSwitchWhen directives.
Is there any flaw in this approach?
Any alternative solution?

Sonny Michaud

unread,
Feb 19, 2014, 11:14:21 AM2/19/14
to ang...@googlegroups.com
I have done something similar and decided to create a generalized hooking mechanism.  In this way, you can define hook points in the parent controller and simply define methods on the child controller scope that will be automatically called at the appropriate point in time.  You can then do whatever you want with the results from the child controllers, if need be, or simply discard them.  I also discuss the tradeoffs between this approach, shared state in services, and sending events back and forth.  You can see my write up here:  http://sonnym.github.io/2014/02/05/hooks-in-angularjs-controllers/

- Sonny
To unsubscribe from this group and stop receiving emails from it, send an email to angular+u...@googlegroups.com.

To post to this group, send email to ang...@googlegroups.com.

Vittorio C.

unread,
Feb 19, 2014, 12:39:55 PM2/19/14
to ang...@googlegroups.com
Thanks Sonny, interesting reading.
I see a few drawbacks in you approach (correct me if I'm wrong) applied to my needs:
  • As long as no interface is declared, there is a risk that I can call a method with same name on an unaware controller (not a "child controller").
  • The message is still a broadcast, this does not solve my flow problem.
    Oversimplifying:
      if (child[i].getResult() > 0 && child[i].isNotBlocking())
          child[i+1].doSomeStuff();
  • The traverse is executed every time RegisterHook is called
The solution I'm trying to implement would rather couple the directive's controllers if possible.

Sonny Michaud

unread,
Feb 19, 2014, 10:00:50 PM2/19/14
to ang...@googlegroups.com
It will only call controllers that are children, but you are correct that you do risk calling methods unintentionally if you are not careful.  In my use case, I was simply able to use a naming convention and that was good enough.  As far as the third point is concerned, RegisterHook may not be the best name for what I am doing, since it is what actually calls all the hook methods.  You could cache the results if they did not change, but in my case this performed sufficiently well and was not a concern.

Based on your example, however, it sounds like you will need a service with a more robust API to interact with.  It sounds like you want a parent controller to mediate between arbitrary child controllers, which I think you could do in a fashion similar to mine, but with additional restrictions.  I guess it really depends on what you are trying to do; if, like in your example, you want them to interact in an ordered manner, it might make sense to traverse the controller structure, but if not that is probably overkill.  If you know exactly which controllers are going to be communicating with each other, you can probably do something like the following:  https://gist.github.com/sonnym/9106358

Be warned, I just threw that together in a few minutes, so there are almost certainly errors.  But I think I would take an approach along those lines, and it should be fairly testable with all the pieces in isolation communicating through a simple API.  I hope this helps.

- Sonny

Mayank Dixit

unread,
Sep 19, 2014, 2:29:08 AM9/19/14
to ang...@googlegroups.com
change angular external link, choose one from fiddle options and reload. It will work.
Message has been deleted

Sander Elias

unread,
Nov 28, 2018, 2:27:47 AM11/28/18
to Angular and AngularJS discussion
Hi Shrinivas 

Can you please stop promoting your blog on old issues? I don't think anyone is interested in reviving a 4 years old thread. Especially not for AngularJS content.

Regards
Sander
Reply all
Reply to author
Forward
0 new messages