3

Using Angular JS - UI Router, I need to communicate from my parent view project.details to my child view project.details.tasks. How can my child view access the scope of the parent view? Also I would like my parent view to be able to call functions on my child view? How can I do this?

This is a rough example of what I am trying to do:

.state('project.details', {
        url: "/:id",
        template: '<a ng-click="[target-route??]>childFunction()">',
        controller: function($scope){
            $scope.parentString = "parent value";
        }
    })
.state('project.details.tasks', {
        url: "/tasks",
        templateUrl: "project.details.tasks.html",
        controller: function($scope){
           console.log("how do I get" + $scope.parentString + " here?";

           $scope.childFunction = function() { console.log('Parent calling');


        }
    })
Holland Risley
  • 6,969
  • 9
  • 25
  • 34

4 Answers4

7

There are actually two questions here:

1) How to access the $scope of the parent:

This is simply solved by using $scope.$parent.... (Solution provided by @ndpu)

2) How to call functions within the child view from the parent:

The solution that I have found for this is to create a shared service, here called broadcastService. Both parent and child view's controllers inject this service. This service uses $rootscope to broadcast events, and the child controller can listen for this event:

The Broadcast Service:

.factory('broadcastService', function ($rootScope) {
    var broadcastService = {};

    broadcastService.message = '';

    broadcastService.prepForBroadcast = function (msg) {
        this.message = msg;
        this.broadcastItem();
    };

    broadcastService.broadcastItem = function () {
        $rootScope.$broadcast('handleBroadcast');
    };

    return broadcastService;
});

The broadcasting controller, which injects the above shared service:

myApp.controller('projectTasksController', ['broadcastService', '$scope', function (broadcastService, $scope) {

        $scope.sendMessageToChildView = function () {
           broadcastService.prepForBroadcast("hello there");
        }
}]);

The receiving controller which also injects the shared service:

.controller('projectsTaskListController', ['broadcastService', '$scope', function (broadcastService, $scope) {
        $scope.output = "";
        $scope.$on('handleBroadcast', function () {
            $scope.output = 'Received: ' + broadcastService.message;
        });

    }]);
Holland Risley
  • 6,969
  • 9
  • 25
  • 34
  • Hi, please note, that for 2) the factory and $rootScope is not really needed. You could just do $scope.$broadcast in the parent controller and $scope.$on in the child controller to call downwards the scope hierarchy OR you could do $scope.$emit in the child controller and $scope.$on in the parent controller to make a call upwards (see docs). You might also be interested in the performance of $broadcast vs $emit [link](http://stackoverflow.com/questions/11252780/whats-the-correct-way-to-communicate-between-controllers-in-angularjs) – mbernath Sep 02 '14 at 19:54
  • how about using a webworker as an event bus? [link](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers#Shared_workers) – verrochio Jul 02 '16 at 19:32
3

Rather than save the information on $scope save it on a service/factory.

Then inject the service into any controller you wish to read the stored (and now shared) data.

This is one method of how you pass data around your application.

Greg
  • 31,180
  • 18
  • 65
  • 85
  • OK, this will work for variables, thanks! How would I call functions on the child? – Holland Risley May 31 '14 at 08:11
  • If its a common function a service would also be appropriate. Or maybe a directive if it's shared UI functionality. – Greg May 31 '14 at 08:42
  • Could I add event listeners and dispatchers in this way? I have a button in the parent that I want to call a function on the child view. – Holland Risley May 31 '14 at 11:12
  • The functionality would reside in the service. All you need to do is assign either the service or the function on the service to a $scope variable and hook up your HTML – Greg May 31 '14 at 15:50
2

You cant access child scope from parent but without problems parent scope can be accessed from child. So, you can place all data and functions that you need to share between states in parent (project.details) scope.

That should work:

// parent state
console.log("Value of parentString from parent scope: " + $scope.parentString);

If you need to change variable in parent scope, you should add $parent before variable name:

// child state
$scope.$parent.parentString = 'new val';
Community
  • 1
  • 1
ndpu
  • 22,225
  • 6
  • 54
  • 69
  • I am still not sure how I can call a function within the child view from the parent? I have a button in the parent which I want to call an action in the child view. Is this not possible? I suppose I could watch a variable in the parent but this seems a little hacky? – Holland Risley May 31 '14 at 11:07
  • Is there a way to add event listeners to the child view? Then dispatch events from the parent? – Holland Risley May 31 '14 at 11:09
  • @HollandRisley "I have a button in the parent which I want to call an action in the child view" - just place that function (action) and data in parent scope... – ndpu Jun 01 '14 at 09:39
  • Yes, you are right this would work for simple views that can hold all methods and data in the parent. But for complex applications, with lots of functionality within the child views, I think the event broadcast style solution below also works really well. – Holland Risley Jun 01 '14 at 17:29
1

why don't you share a service or a factory between the two scopes and creat an api using that service or factory and then call its functions to handle the scopes, i feel this is the correct way because then things are more decoupled.

Imal Hasaranga Perera
  • 9,683
  • 3
  • 51
  • 41
  • This works for me. Although, being new in angularjs, I don't know the implication of this. I share an empty function as the service, and all the controllers just passes data by setting values in the service. Any bad implications here? – antony Apr 04 '16 at 06:08